authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2025-05-20 03:25:19+01:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2025-05-20 03:25:19+01:00
log23c817548bbd3988a5fd224b590a4f6102dbe5db
tree5448478794cb493b456de356c2e29fb100e81cfb
parentf2077f57ae03ef21f1bfee6e4e041c5f466fc3be
parent37a9a4e0f16c1df8de3a4add3a9566b24f024a95
signaturebadge-check Signed by PGP key B5690EEEBB952194

Merge pull request #23836 from mlugg/incr-fixes

Incremental fixes, refactor `Zcu.File`

53 files changed, 2796 insertions(+), 2394 deletions(-)

build.zig+11-6
...@@ -508,11 +508,9 @@ pub fn build(b: *std.Build) !void {...@@ -508,11 +508,9 @@ pub fn build(b: *std.Build) !void {
508 test_step.dependOn(unit_tests_step);508 test_step.dependOn(unit_tests_step);
509509
510 const unit_tests = b.addTest(.{510 const unit_tests = b.addTest(.{
511 .root_module = b.createModule(.{511 .root_module = addCompilerMod(b, .{
512 .root_source_file = b.path("src/main.zig"),
513 .optimize = optimize,512 .optimize = optimize,
514 .target = target,513 .target = target,
515 .link_libc = link_libc,
516 .single_threaded = single_threaded,514 .single_threaded = single_threaded,
517 }),515 }),
518 .filters = test_filters,516 .filters = test_filters,
...@@ -520,6 +518,9 @@ pub fn build(b: *std.Build) !void {...@@ -520,6 +518,9 @@ pub fn build(b: *std.Build) !void {
520 .use_lld = use_llvm,518 .use_lld = use_llvm,
521 .zig_lib_dir = b.path("lib"),519 .zig_lib_dir = b.path("lib"),
522 });520 });
521 if (link_libc) {
522 unit_tests.root_module.link_libc = true;
523 }
523 unit_tests.root_module.addOptions("build_options", exe_options);524 unit_tests.root_module.addOptions("build_options", exe_options);
524 unit_tests_step.dependOn(&b.addRunArtifact(unit_tests).step);525 unit_tests_step.dependOn(&b.addRunArtifact(unit_tests).step);
525526
...@@ -650,7 +651,7 @@ fn addWasiUpdateStep(b: *std.Build, version: [:0]const u8) !void {...@@ -650,7 +651,7 @@ fn addWasiUpdateStep(b: *std.Build, version: [:0]const u8) !void {
650 update_zig1_step.dependOn(&copy_zig_h.step);651 update_zig1_step.dependOn(&copy_zig_h.step);
651}652}
652653
653const AddCompilerStepOptions = struct {654const AddCompilerModOptions = struct {
654 optimize: std.builtin.OptimizeMode,655 optimize: std.builtin.OptimizeMode,
655 target: std.Build.ResolvedTarget,656 target: std.Build.ResolvedTarget,
656 strip: ?bool = null,657 strip: ?bool = null,
...@@ -659,7 +660,7 @@ const AddCompilerStepOptions = struct {...@@ -659,7 +660,7 @@ const AddCompilerStepOptions = struct {
659 single_threaded: ?bool = null,660 single_threaded: ?bool = null,
660};661};
661662
662fn addCompilerStep(b: *std.Build, options: AddCompilerStepOptions) *std.Build.Step.Compile {663fn addCompilerMod(b: *std.Build, options: AddCompilerModOptions) *std.Build.Module {
663 const compiler_mod = b.createModule(.{664 const compiler_mod = b.createModule(.{
664 .root_source_file = b.path("src/main.zig"),665 .root_source_file = b.path("src/main.zig"),
665 .target = options.target,666 .target = options.target,
...@@ -682,10 +683,14 @@ fn addCompilerStep(b: *std.Build, options: AddCompilerStepOptions) *std.Build.St...@@ -682,10 +683,14 @@ fn addCompilerStep(b: *std.Build, options: AddCompilerStepOptions) *std.Build.St
682 compiler_mod.addImport("aro", aro_mod);683 compiler_mod.addImport("aro", aro_mod);
683 compiler_mod.addImport("aro_translate_c", aro_translate_c_mod);684 compiler_mod.addImport("aro_translate_c", aro_translate_c_mod);
684685
686 return compiler_mod;
687}
688
689fn addCompilerStep(b: *std.Build, options: AddCompilerModOptions) *std.Build.Step.Compile {
685 const exe = b.addExecutable(.{690 const exe = b.addExecutable(.{
686 .name = "zig",691 .name = "zig",
687 .max_rss = 7_800_000_000,692 .max_rss = 7_800_000_000,
688 .root_module = compiler_mod,693 .root_module = addCompilerMod(b, options),
689 });694 });
690 exe.stack_size = stack_size;695 exe.stack_size = stack_size;
691696
lib/std/Build/Cache.zig+2-3
...@@ -1011,17 +1011,16 @@ pub const Manifest = struct {...@@ -1011,17 +1011,16 @@ pub const Manifest = struct {
1011 }1011 }
10121012
1013 /// Like `addFilePost` but when the file contents have already been loaded from disk.1013 /// Like `addFilePost` but when the file contents have already been loaded from disk.
1014 /// On success, cache takes ownership of `resolved_path`.
1015 pub fn addFilePostContents(1014 pub fn addFilePostContents(
1016 self: *Manifest,1015 self: *Manifest,
1017 resolved_path: []u8,1016 file_path: []const u8,
1018 bytes: []const u8,1017 bytes: []const u8,
1019 stat: File.Stat,1018 stat: File.Stat,
1020 ) !void {1019 ) !void {
1021 assert(self.manifest_file != null);1020 assert(self.manifest_file != null);
1022 const gpa = self.cache.gpa;1021 const gpa = self.cache.gpa;
10231022
1024 const prefixed_path = try self.cache.findPrefixResolved(resolved_path);1023 const prefixed_path = try self.cache.findPrefix(file_path);
1025 errdefer gpa.free(prefixed_path.sub_path);1024 errdefer gpa.free(prefixed_path.sub_path);
10261025
1027 const gop = try self.files.getOrPutAdapted(gpa, prefixed_path, FilesAdapter{});1026 const gop = try self.files.getOrPutAdapted(gpa, prefixed_path, FilesAdapter{});
src/Builtin.zig+64-27
...@@ -19,6 +19,26 @@ code_model: std.builtin.CodeModel,...@@ -19,6 +19,26 @@ code_model: std.builtin.CodeModel,
19omit_frame_pointer: bool,19omit_frame_pointer: bool,
20wasi_exec_model: std.builtin.WasiExecModel,20wasi_exec_model: std.builtin.WasiExecModel,
2121
22/// Compute an abstract hash representing this `Builtin`. This is *not* a hash
23/// of the resulting file contents.
24pub fn hash(opts: @This()) [std.Build.Cache.bin_digest_len]u8 {
25 var h: Cache.Hasher = Cache.hasher_init;
26 inline for (@typeInfo(@This()).@"struct".fields) |f| {
27 if (comptime std.mem.eql(u8, f.name, "target")) {
28 // This needs special handling.
29 std.hash.autoHash(&h, opts.target.cpu);
30 std.hash.autoHash(&h, opts.target.os.tag);
31 std.hash.autoHash(&h, opts.target.os.versionRange());
32 std.hash.autoHash(&h, opts.target.abi);
33 std.hash.autoHash(&h, opts.target.ofmt);
34 std.hash.autoHash(&h, opts.target.dynamic_linker);
35 } else {
36 std.hash.autoHash(&h, @field(opts, f.name));
37 }
38 }
39 return h.finalResult();
40}
41
22pub fn generate(opts: @This(), allocator: Allocator) Allocator.Error![:0]u8 {42pub fn generate(opts: @This(), allocator: Allocator) Allocator.Error![:0]u8 {
23 var buffer = std.ArrayList(u8).init(allocator);43 var buffer = std.ArrayList(u8).init(allocator);
24 try append(opts, &buffer);44 try append(opts, &buffer);
...@@ -263,50 +283,66 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void {...@@ -263,50 +283,66 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void {
263 }283 }
264}284}
265285
266pub fn populateFile(comp: *Compilation, mod: *Module, file: *File) !void {286/// This essentially takes the place of `Zcu.PerThread.updateFile`, but for 'builtin' modules.
267 if (mod.root.statFile(mod.root_src_path)) |stat| {287/// Instead of reading the file from disk, its contents are generated in-memory.
288pub fn populateFile(opts: @This(), gpa: Allocator, file: *File) Allocator.Error!void {
289 assert(file.is_builtin);
290 assert(file.status == .never_loaded);
291 assert(file.source == null);
292 assert(file.tree == null);
293 assert(file.zir == null);
294
295 file.source = try opts.generate(gpa);
296
297 log.debug("parsing and generating 'builtin.zig'", .{});
298
299 file.tree = try std.zig.Ast.parse(gpa, file.source.?, .zig);
300 assert(file.tree.?.errors.len == 0); // builtin.zig must parse
301
302 file.zir = try AstGen.generate(gpa, file.tree.?);
303 assert(!file.zir.?.hasCompileErrors()); // builtin.zig must not have astgen errors
304 file.status = .success;
305}
306
307/// After `populateFile` succeeds, call this function to write the generated file out to disk
308/// if necessary. This is useful for external tooling such as debuggers.
309/// Assumes that `file.mod` is correctly set to the builtin module.
310pub fn updateFileOnDisk(file: *File, comp: *Compilation) !void {
311 assert(file.is_builtin);
312 assert(file.status == .success);
313 assert(file.source != null);
314
315 const root_dir, const sub_path = file.path.openInfo(comp.dirs);
316
317 if (root_dir.statFile(sub_path)) |stat| {
268 if (stat.size != file.source.?.len) {318 if (stat.size != file.source.?.len) {
269 std.log.warn(319 std.log.warn(
270 "the cached file '{}{s}' had the wrong size. Expected {d}, found {d}. " ++320 "the cached file '{}' had the wrong size. Expected {d}, found {d}. " ++
271 "Overwriting with correct file contents now",321 "Overwriting with correct file contents now",
272 .{ mod.root, mod.root_src_path, file.source.?.len, stat.size },322 .{ file.path.fmt(comp), file.source.?.len, stat.size },
273 );323 );
274
275 try writeFile(file, mod);
276 } else {324 } else {
277 file.stat = .{325 file.stat = .{
278 .size = stat.size,326 .size = stat.size,
279 .inode = stat.inode,327 .inode = stat.inode,
280 .mtime = stat.mtime,328 .mtime = stat.mtime,
281 };329 };
330 return;
282 }331 }
283 } else |err| switch (err) {332 } else |err| switch (err) {
284 error.BadPathName => unreachable, // it's always "builtin.zig"333 error.FileNotFound => {},
285 error.NameTooLong => unreachable, // it's always "builtin.zig"
286 error.PipeBusy => unreachable, // it's not a pipe
287 error.NoDevice => unreachable, // it's not a pipe
288 error.WouldBlock => unreachable, // not asking for non-blocking I/O
289334
290 error.FileNotFound => try writeFile(file, mod),335 error.WouldBlock => unreachable, // not asking for non-blocking I/O
336 error.BadPathName => unreachable, // it's always "o/digest/builtin.zig"
337 error.NameTooLong => unreachable, // it's always "o/digest/builtin.zig"
291338
339 // We don't expect the file to be a pipe, but can't mark `error.PipeBusy` as `unreachable`,
340 // because the user could always replace the file on disk.
292 else => |e| return e,341 else => |e| return e,
293 }342 }
294343
295 log.debug("parsing and generating '{s}'", .{mod.root_src_path});344 // `make_path` matters because the dir hasn't actually been created yet.
296345 var af = try root_dir.atomicFile(sub_path, .{ .make_path = true });
297 file.tree = try std.zig.Ast.parse(comp.gpa, file.source.?, .zig);
298 assert(file.tree.?.errors.len == 0); // builtin.zig must parse
299
300 file.zir = try AstGen.generate(comp.gpa, file.tree.?);
301 assert(!file.zir.?.hasCompileErrors()); // builtin.zig must not have astgen errors
302 file.status = .success;
303 // Note that whilst we set `zir` here, we populated `path_digest`
304 // all the way back in `Package.Module.create`.
305}
306
307fn writeFile(file: *File, mod: *Module) !void {
308 var buf: [std.fs.max_path_bytes]u8 = undefined;
309 var af = try mod.root.atomicFile(mod.root_src_path, .{ .make_path = true }, &buf);
310 defer af.deinit();346 defer af.deinit();
311 try af.file.writeAll(file.source.?);347 try af.file.writeAll(file.source.?);
312 af.finish() catch |err| switch (err) {348 af.finish() catch |err| switch (err) {
...@@ -331,6 +367,7 @@ fn writeFile(file: *File, mod: *Module) !void {...@@ -331,6 +367,7 @@ fn writeFile(file: *File, mod: *Module) !void {
331const builtin = @import("builtin");367const builtin = @import("builtin");
332const std = @import("std");368const std = @import("std");
333const Allocator = std.mem.Allocator;369const Allocator = std.mem.Allocator;
370const Cache = std.Build.Cache;
334const build_options = @import("build_options");371const build_options = @import("build_options");
335const Module = @import("Package/Module.zig");372const Module = @import("Package/Module.zig");
336const assert = std.debug.assert;373const assert = std.debug.assert;
src/Compilation.zig+830-577
...@@ -2,6 +2,7 @@ const Compilation = @This();...@@ -2,6 +2,7 @@ const Compilation = @This();
22
3const std = @import("std");3const std = @import("std");
4const builtin = @import("builtin");4const builtin = @import("builtin");
5const fs = std.fs;
5const mem = std.mem;6const mem = std.mem;
6const Allocator = std.mem.Allocator;7const Allocator = std.mem.Allocator;
7const assert = std.debug.assert;8const assert = std.debug.assert;
...@@ -10,12 +11,13 @@ const Target = std.Target;...@@ -10,12 +11,13 @@ const Target = std.Target;
10const ThreadPool = std.Thread.Pool;11const ThreadPool = std.Thread.Pool;
11const WaitGroup = std.Thread.WaitGroup;12const WaitGroup = std.Thread.WaitGroup;
12const ErrorBundle = std.zig.ErrorBundle;13const ErrorBundle = std.zig.ErrorBundle;
13const Path = Cache.Path;14const fatal = std.process.fatal;
1415
15const Value = @import("Value.zig");16const Value = @import("Value.zig");
16const Type = @import("Type.zig");17const Type = @import("Type.zig");
17const target_util = @import("target.zig");18const target_util = @import("target.zig");
18const Package = @import("Package.zig");19const Package = @import("Package.zig");
20const introspect = @import("introspect.zig");
19const link = @import("link.zig");21const link = @import("link.zig");
20const tracy = @import("tracy.zig");22const tracy = @import("tracy.zig");
21const trace = tracy.trace;23const trace = tracy.trace;
...@@ -28,7 +30,6 @@ const mingw = @import("libs/mingw.zig");...@@ -28,7 +30,6 @@ const mingw = @import("libs/mingw.zig");
28const libunwind = @import("libs/libunwind.zig");30const libunwind = @import("libs/libunwind.zig");
29const libcxx = @import("libs/libcxx.zig");31const libcxx = @import("libs/libcxx.zig");
30const wasi_libc = @import("libs/wasi_libc.zig");32const wasi_libc = @import("libs/wasi_libc.zig");
31const fatal = @import("main.zig").fatal;
32const clangMain = @import("main.zig").clangMain;33const clangMain = @import("main.zig").clangMain;
33const Zcu = @import("Zcu.zig");34const Zcu = @import("Zcu.zig");
34const Sema = @import("Sema.zig");35const Sema = @import("Sema.zig");
...@@ -43,7 +44,6 @@ const LlvmObject = @import("codegen/llvm.zig").Object;...@@ -43,7 +44,6 @@ const LlvmObject = @import("codegen/llvm.zig").Object;
43const dev = @import("dev.zig");44const dev = @import("dev.zig");
44const ThreadSafeQueue = @import("ThreadSafeQueue.zig").ThreadSafeQueue;45const ThreadSafeQueue = @import("ThreadSafeQueue.zig").ThreadSafeQueue;
4546
46pub const Directory = Cache.Directory;
47pub const Config = @import("Compilation/Config.zig");47pub const Config = @import("Compilation/Config.zig");
4848
49/// General-purpose allocator. Used for both temporary and long-term storage.49/// General-purpose allocator. Used for both temporary and long-term storage.
...@@ -75,9 +75,9 @@ bin_file: ?*link.File,...@@ -75,9 +75,9 @@ bin_file: ?*link.File,
75/// The root path for the dynamic linker and system libraries (as well as frameworks on Darwin)75/// The root path for the dynamic linker and system libraries (as well as frameworks on Darwin)
76sysroot: ?[]const u8,76sysroot: ?[]const u8,
77/// This is `null` when not building a Windows DLL, or when `-fno-emit-implib` is used.77/// This is `null` when not building a Windows DLL, or when `-fno-emit-implib` is used.
78implib_emit: ?Path,78implib_emit: ?Cache.Path,
79/// This is non-null when `-femit-docs` is provided.79/// This is non-null when `-femit-docs` is provided.
80docs_emit: ?Path,80docs_emit: ?Cache.Path,
81root_name: [:0]const u8,81root_name: [:0]const u8,
82compiler_rt_strat: RtStrat,82compiler_rt_strat: RtStrat,
83ubsan_rt_strat: RtStrat,83ubsan_rt_strat: RtStrat,
...@@ -152,11 +152,6 @@ win32_resource_work_queue: if (dev.env.supports(.win32_resource)) std.fifo.Linea...@@ -152,11 +152,6 @@ win32_resource_work_queue: if (dev.env.supports(.win32_resource)) std.fifo.Linea
152 pub fn deinit(_: @This()) void {}152 pub fn deinit(_: @This()) void {}
153},153},
154154
155/// These jobs are to tokenize, parse, and astgen files, which may be outdated
156/// since the last compilation, as well as scan for `@import` and queue up
157/// additional jobs corresponding to those new files.
158astgen_work_queue: std.fifo.LinearFifo(Zcu.File.Index, .Dynamic),
159
160/// The ErrorMsg memory is owned by the `CObject`, using Compilation's general purpose allocator.155/// The ErrorMsg memory is owned by the `CObject`, using Compilation's general purpose allocator.
161/// This data is accessed by multiple threads and is protected by `mutex`.156/// This data is accessed by multiple threads and is protected by `mutex`.
162failed_c_objects: std.AutoArrayHashMapUnmanaged(*CObject, *CObject.Diag.Bundle) = .empty,157failed_c_objects: std.AutoArrayHashMapUnmanaged(*CObject, *CObject.Diag.Bundle) = .empty,
...@@ -207,9 +202,8 @@ cache_parent: *Cache,...@@ -207,9 +202,8 @@ cache_parent: *Cache,
207parent_whole_cache: ?ParentWholeCache,202parent_whole_cache: ?ParentWholeCache,
208/// Path to own executable for invoking `zig clang`.203/// Path to own executable for invoking `zig clang`.
209self_exe_path: ?[]const u8,204self_exe_path: ?[]const u8,
210zig_lib_directory: Directory,205/// Owned by the caller of `Compilation.create`.
211local_cache_directory: Directory,206dirs: Directories,
212global_cache_directory: Directory,
213libc_include_dir_list: []const []const u8,207libc_include_dir_list: []const []const u8,
214libc_framework_dir_list: []const []const u8,208libc_framework_dir_list: []const []const u8,
215rc_includes: RcIncludes,209rc_includes: RcIncludes,
...@@ -293,7 +287,6 @@ const QueuedJobs = struct {...@@ -293,7 +287,6 @@ const QueuedJobs = struct {
293 ubsan_rt_lib: bool = false,287 ubsan_rt_lib: bool = false,
294 ubsan_rt_obj: bool = false,288 ubsan_rt_obj: bool = false,
295 fuzzer_lib: bool = false,289 fuzzer_lib: bool = false,
296 update_builtin_zig: bool,
297 musl_crt_file: [@typeInfo(musl.CrtFile).@"enum".fields.len]bool = @splat(false),290 musl_crt_file: [@typeInfo(musl.CrtFile).@"enum".fields.len]bool = @splat(false),
298 glibc_crt_file: [@typeInfo(glibc.CrtFile).@"enum".fields.len]bool = @splat(false),291 glibc_crt_file: [@typeInfo(glibc.CrtFile).@"enum".fields.len]bool = @splat(false),
299 freebsd_crt_file: [@typeInfo(freebsd.CrtFile).@"enum".fields.len]bool = @splat(false),292 freebsd_crt_file: [@typeInfo(freebsd.CrtFile).@"enum".fields.len]bool = @splat(false),
...@@ -312,12 +305,466 @@ const QueuedJobs = struct {...@@ -312,12 +305,466 @@ const QueuedJobs = struct {
312 zigc_lib: bool = false,305 zigc_lib: bool = false,
313};306};
314307
308/// A filesystem path, represented relative to one of a few specific directories where possible.
309/// Every path (considering symlinks as distinct paths) has a canonical representation in this form.
310/// This abstraction allows us to:
311/// * always open files relative to a consistent root on the filesystem
312/// * detect when two paths correspond to the same file, e.g. for deduplicating `@import`s
313pub const Path = struct {
314 root: Root,
315 /// This path is always in a normalized form, where:
316 /// * All components are separated by `fs.path.sep`
317 /// * There are no repeated separators (like "foo//bar")
318 /// * There are no "." or ".." components
319 /// * There is no trailing path separator
320 ///
321 /// There is a leading separator iff `root` is `.none` *and* `builtin.target.os.tag != .wasi`.
322 ///
323 /// If this `Path` exactly represents a `Root`, the sub path is "", not ".".
324 sub_path: []u8,
325
326 const Root = enum {
327 /// `sub_path` is relative to the Zig lib directory on `Compilation`.
328 zig_lib,
329 /// `sub_path` is relative to the global cache directory on `Compilation`.
330 global_cache,
331 /// `sub_path` is relative to the local cache directory on `Compilation`.
332 local_cache,
333 /// `sub_path` is not relative to any of the roots listed above.
334 /// It is resolved starting with `Directories.cwd`; so it is an absolute path on most
335 /// targets, but cwd-relative on WASI. We do not make it cwd-relative on other targets
336 /// so that `Path.digest` gives hashes which can be stored in the Zig cache (as they
337 /// don't depend on a specific compiler instance).
338 none,
339 };
340
341 /// In general, we can only construct canonical `Path`s at runtime, because weird nesting might
342 /// mean that e.g. a sub path inside zig/lib/ is actually in the global cache. However, because
343 /// `Directories` guarantees that `zig_lib` is a distinct path from both cache directories, it's
344 /// okay for us to construct this path, and only this path, as a comptime constant.
345 pub const zig_lib_root: Path = .{ .root = .zig_lib, .sub_path = "" };
346
347 pub fn deinit(p: Path, gpa: Allocator) void {
348 gpa.free(p.sub_path);
349 }
350
351 /// The returned digest is relocatable across any compiler process using the same lib and cache
352 /// directories; it does not depend on cwd.
353 pub fn digest(p: Path) Cache.BinDigest {
354 var h = Cache.hasher_init;
355 h.update(&.{@intFromEnum(p.root)});
356 h.update(p.sub_path);
357 return h.finalResult();
358 }
359
360 /// Given a `Path`, returns the directory handle and sub path to be used to open the path.
361 pub fn openInfo(p: Path, dirs: Directories) struct { fs.Dir, []const u8 } {
362 const dir = switch (p.root) {
363 .none => {
364 const cwd_sub_path = absToCwdRelative(p.sub_path, dirs.cwd);
365 return .{ fs.cwd(), cwd_sub_path };
366 },
367 .zig_lib => dirs.zig_lib.handle,
368 .global_cache => dirs.global_cache.handle,
369 .local_cache => dirs.local_cache.handle,
370 };
371 if (p.sub_path.len == 0) return .{ dir, "." };
372 assert(!fs.path.isAbsolute(p.sub_path));
373 return .{ dir, p.sub_path };
374 }
375
376 pub const format = unreachable; // do not format direcetly
377 pub fn fmt(p: Path, comp: *Compilation) Formatter {
378 return .{ .p = p, .comp = comp };
379 }
380 const Formatter = struct {
381 p: Path,
382 comp: *Compilation,
383 pub fn format(f: Formatter, comptime unused_fmt: []const u8, options: std.fmt.FormatOptions, w: anytype) !void {
384 comptime assert(unused_fmt.len == 0);
385 _ = options;
386 const root_path: []const u8 = switch (f.p.root) {
387 .zig_lib => f.comp.dirs.zig_lib.path orelse ".",
388 .global_cache => f.comp.dirs.global_cache.path orelse ".",
389 .local_cache => f.comp.dirs.local_cache.path orelse ".",
390 .none => {
391 const cwd_sub_path = absToCwdRelative(f.p.sub_path, f.comp.dirs.cwd);
392 try w.writeAll(cwd_sub_path);
393 return;
394 },
395 };
396 assert(root_path.len != 0);
397 try w.writeAll(root_path);
398 if (f.p.sub_path.len > 0) {
399 try w.writeByte(fs.path.sep);
400 try w.writeAll(f.p.sub_path);
401 }
402 }
403 };
404
405 /// Given the `sub_path` of a `Path` with `Path.root == .none`, attempts to convert
406 /// the (absolute) path to a cwd-relative path. Otherwise, returns the absolute path
407 /// unmodified. The returned string is never empty: "" is converted to ".".
408 fn absToCwdRelative(sub_path: []const u8, cwd_path: []const u8) []const u8 {
409 if (builtin.target.os.tag == .wasi) {
410 if (sub_path.len == 0) return ".";
411 assert(!fs.path.isAbsolute(sub_path));
412 return sub_path;
413 }
414 assert(fs.path.isAbsolute(sub_path));
415 if (!std.mem.startsWith(u8, sub_path, cwd_path)) return sub_path;
416 if (sub_path.len == cwd_path.len) return "."; // the strings are equal
417 if (sub_path[cwd_path.len] != fs.path.sep) return sub_path; // last component before cwd differs
418 return sub_path[cwd_path.len + 1 ..]; // remove '/path/to/cwd/' prefix
419 }
420
421 /// From an unresolved path (which can be made of multiple not-yet-joined strings), construct a
422 /// canonical `Path`.
423 pub fn fromUnresolved(gpa: Allocator, dirs: Compilation.Directories, unresolved_parts: []const []const u8) Allocator.Error!Path {
424 const resolved = try introspect.resolvePath(gpa, dirs.cwd, unresolved_parts);
425 errdefer gpa.free(resolved);
426
427 // If, for instance, `dirs.local_cache.path` is within the lib dir, it must take priority,
428 // so that we prefer `.root = .local_cache` over `.root = .zig_lib`. The easiest way to do
429 // this is simply to prioritize the longest root path.
430 const PathAndRoot = struct { ?[]const u8, Root };
431 var roots: [3]PathAndRoot = .{
432 .{ dirs.zig_lib.path, .zig_lib },
433 .{ dirs.global_cache.path, .global_cache },
434 .{ dirs.local_cache.path, .local_cache },
435 };
436 // This must be a stable sort, because the global and local cache directories may be the same, in
437 // which case we need to make a consistent choice.
438 std.mem.sort(PathAndRoot, &roots, {}, struct {
439 fn lessThan(_: void, lhs: PathAndRoot, rhs: PathAndRoot) bool {
440 const lhs_path_len = if (lhs[0]) |p| p.len else 0;
441 const rhs_path_len = if (rhs[0]) |p| p.len else 0;
442 return lhs_path_len > rhs_path_len; // '>' instead of '<' to sort descending
443 }
444 }.lessThan);
445
446 for (roots) |path_and_root| {
447 const opt_root_path, const root = path_and_root;
448 const root_path = opt_root_path orelse {
449 // This root is the cwd.
450 if (!fs.path.isAbsolute(resolved)) {
451 return .{
452 .root = root,
453 .sub_path = resolved,
454 };
455 }
456 continue;
457 };
458 if (!mem.startsWith(u8, resolved, root_path)) continue;
459 const sub: []const u8 = if (resolved.len != root_path.len) sub: {
460 // Check the trailing slash, so that we don't match e.g. `/foo/bar` with `/foo/barren`
461 if (resolved[root_path.len] != fs.path.sep) continue;
462 break :sub resolved[root_path.len + 1 ..];
463 } else "";
464 const duped = try gpa.dupe(u8, sub);
465 gpa.free(resolved);
466 return .{ .root = root, .sub_path = duped };
467 }
468
469 // We're not relative to any root, so we will use an absolute path (on targets where they are available).
470
471 if (builtin.target.os.tag == .wasi or fs.path.isAbsolute(resolved)) {
472 // `resolved` is already absolute (or we're on WASI, where absolute paths don't really exist).
473 return .{ .root = .none, .sub_path = resolved };
474 }
475
476 if (resolved.len == 0) {
477 // We just need the cwd path, no trailing separator. Note that `gpa.free(resolved)` would be a nop.
478 return .{ .root = .none, .sub_path = try gpa.dupe(u8, dirs.cwd) };
479 }
480
481 // We need to make an absolute path. Because `resolved` came from `introspect.resolvePath`, we can just
482 // join the paths with a simple format string.
483 const abs_path = try std.fmt.allocPrint(gpa, "{s}{c}{s}", .{ dirs.cwd, fs.path.sep, resolved });
484 gpa.free(resolved);
485 return .{ .root = .none, .sub_path = abs_path };
486 }
487
488 /// Constructs a canonical `Path` representing `sub_path` relative to `root`.
489 ///
490 /// If `sub_path` is resolved, this is almost like directly constructing a `Path`, but this
491 /// function also canonicalizes the result, which matters because `sub_path` may move us into
492 /// a different root.
493 ///
494 /// For instance, if the Zig lib directory is inside the global cache, passing `root` as
495 /// `.global_cache` could still end up returning a `Path` with `Path.root == .zig_lib`.
496 pub fn fromRoot(
497 gpa: Allocator,
498 dirs: Compilation.Directories,
499 root: Path.Root,
500 sub_path: []const u8,
501 ) Allocator.Error!Path {
502 // Currently, this just wraps `fromUnresolved` for simplicity. A more efficient impl is
503 // probably possible if this function ever ends up impacting performance somehow.
504 return .fromUnresolved(gpa, dirs, &.{
505 switch (root) {
506 .zig_lib => dirs.zig_lib.path orelse "",
507 .global_cache => dirs.global_cache.path orelse "",
508 .local_cache => dirs.local_cache.path orelse "",
509 .none => "",
510 },
511 sub_path,
512 });
513 }
514
515 /// Given a `Path` and an (unresolved) sub path relative to it, construct a `Path` representing
516 /// the joined path `p/sub_path`. Note that, like with `fromRoot`, the `sub_path` might cause us
517 /// to move into a different `Path.Root`.
518 pub fn join(
519 p: Path,
520 gpa: Allocator,
521 dirs: Compilation.Directories,
522 sub_path: []const u8,
523 ) Allocator.Error!Path {
524 // Currently, this just wraps `fromUnresolved` for simplicity. A more efficient impl is
525 // probably possible if this function ever ends up impacting performance somehow.
526 return .fromUnresolved(gpa, dirs, &.{
527 switch (p.root) {
528 .zig_lib => dirs.zig_lib.path orelse "",
529 .global_cache => dirs.global_cache.path orelse "",
530 .local_cache => dirs.local_cache.path orelse "",
531 .none => "",
532 },
533 p.sub_path,
534 sub_path,
535 });
536 }
537
538 /// Like `join`, but `sub_path` is relative to the dirname of `p` instead of `p` itself.
539 pub fn upJoin(
540 p: Path,
541 gpa: Allocator,
542 dirs: Compilation.Directories,
543 sub_path: []const u8,
544 ) Allocator.Error!Path {
545 return .fromUnresolved(gpa, dirs, &.{
546 switch (p.root) {
547 .zig_lib => dirs.zig_lib.path orelse "",
548 .global_cache => dirs.global_cache.path orelse "",
549 .local_cache => dirs.local_cache.path orelse "",
550 .none => "",
551 },
552 p.sub_path,
553 "..",
554 sub_path,
555 });
556 }
557
558 pub fn toCachePath(p: Path, dirs: Directories) Cache.Path {
559 const root_dir: Cache.Directory = switch (p.root) {
560 .zig_lib => dirs.zig_lib,
561 .global_cache => dirs.global_cache,
562 .local_cache => dirs.local_cache,
563 else => {
564 const cwd_sub_path = absToCwdRelative(p.sub_path, dirs.cwd);
565 return .{
566 .root_dir = .cwd(),
567 .sub_path = cwd_sub_path,
568 };
569 },
570 };
571 assert(!fs.path.isAbsolute(p.sub_path));
572 return .{
573 .root_dir = root_dir,
574 .sub_path = p.sub_path,
575 };
576 }
577
578 /// This should not be used for most of the compiler pipeline, but is useful when emitting
579 /// paths from the compilation (e.g. in debug info), because they will not depend on the cwd.
580 /// The returned path is owned by the caller and allocated into `gpa`.
581 pub fn toAbsolute(p: Path, dirs: Directories, gpa: Allocator) Allocator.Error![]u8 {
582 const root_path: []const u8 = switch (p.root) {
583 .zig_lib => dirs.zig_lib.path orelse "",
584 .global_cache => dirs.global_cache.path orelse "",
585 .local_cache => dirs.local_cache.path orelse "",
586 .none => "",
587 };
588 return fs.path.resolve(gpa, &.{
589 dirs.cwd,
590 root_path,
591 p.sub_path,
592 });
593 }
594
595 pub fn isNested(inner: Path, outer: Path) union(enum) {
596 /// Value is the sub path, which is a sub-slice of `inner.sub_path`.
597 yes: []const u8,
598 no,
599 different_roots,
600 } {
601 if (inner.root != outer.root) return .different_roots;
602 if (!mem.startsWith(u8, inner.sub_path, outer.sub_path)) return .no;
603 if (inner.sub_path.len == outer.sub_path.len) return .no;
604 if (outer.sub_path.len == 0) return .{ .yes = inner.sub_path };
605 if (inner.sub_path[outer.sub_path.len] != fs.path.sep) return .no;
606 return .{ .yes = inner.sub_path[outer.sub_path.len + 1 ..] };
607 }
608
609 /// Returns whether this `Path` is illegal to have as a user-imported `Zcu.File` (including
610 /// as the root of a module). Such paths exist in directories which the Zig compiler treats
611 /// specially, like 'global_cache/b/', which stores 'builtin.zig' files.
612 pub fn isIllegalZigImport(p: Path, gpa: Allocator, dirs: Directories) Allocator.Error!bool {
613 const zig_builtin_dir: Path = try .fromRoot(gpa, dirs, .global_cache, "b");
614 defer zig_builtin_dir.deinit(gpa);
615 return switch (p.isNested(zig_builtin_dir)) {
616 .yes => true,
617 .no, .different_roots => false,
618 };
619 }
620};
621
622pub const Directories = struct {
623 /// The string returned by `introspect.getResolvedCwd`. This is typically an absolute path,
624 /// but on WASI is the empty string "" instead, because WASI does not have absolute paths.
625 cwd: []const u8,
626 /// The Zig 'lib' directory.
627 /// `zig_lib.path` is resolved (`introspect.resolvePath`) or `null` for cwd.
628 /// Guaranteed to be a different path from `global_cache` and `local_cache`.
629 zig_lib: Cache.Directory,
630 /// The global Zig cache directory.
631 /// `global_cache.path` is resolved (`introspect.resolvePath`) or `null` for cwd.
632 global_cache: Cache.Directory,
633 /// The local Zig cache directory.
634 /// `local_cache.path` is resolved (`introspect.resolvePath`) or `null` for cwd.
635 /// This may be the same as `global_cache`.
636 local_cache: Cache.Directory,
637
638 pub fn deinit(dirs: *Directories) void {
639 // The local and global caches could be the same.
640 const close_local = dirs.local_cache.handle.fd != dirs.global_cache.handle.fd;
641
642 dirs.global_cache.handle.close();
643 if (close_local) dirs.local_cache.handle.close();
644 dirs.zig_lib.handle.close();
645 }
646
647 /// Returns a `Directories` where `local_cache` is replaced with `global_cache`, intended for
648 /// use by sub-compilations (e.g. compiler_rt). Do not `deinit` the returned `Directories`; it
649 /// shares handles with `dirs`.
650 pub fn withoutLocalCache(dirs: Directories) Directories {
651 return .{
652 .cwd = dirs.cwd,
653 .zig_lib = dirs.zig_lib,
654 .global_cache = dirs.global_cache,
655 .local_cache = dirs.global_cache,
656 };
657 }
658
659 /// Uses `std.process.fatal` on error conditions.
660 pub fn init(
661 arena: Allocator,
662 override_zig_lib: ?[]const u8,
663 override_global_cache: ?[]const u8,
664 local_cache_strat: union(enum) {
665 override: []const u8,
666 search,
667 global,
668 },
669 wasi_preopens: switch (builtin.target.os.tag) {
670 .wasi => std.fs.wasi.Preopens,
671 else => void,
672 },
673 self_exe_path: switch (builtin.target.os.tag) {
674 .wasi => void,
675 else => []const u8,
676 },
677 ) Directories {
678 const wasi = builtin.target.os.tag == .wasi;
679
680 const cwd = introspect.getResolvedCwd(arena) catch |err| {
681 fatal("unable to get cwd: {s}", .{@errorName(err)});
682 };
683
684 const zig_lib: Cache.Directory = d: {
685 if (override_zig_lib) |path| break :d openUnresolved(arena, cwd, path, .@"zig lib");
686 if (wasi) break :d openWasiPreopen(wasi_preopens, "/lib");
687 break :d introspect.findZigLibDirFromSelfExe(arena, cwd, self_exe_path) catch |err| {
688 fatal("unable to find zig installation directory '{s}': {s}", .{ self_exe_path, @errorName(err) });
689 };
690 };
691
692 const global_cache: Cache.Directory = d: {
693 if (override_global_cache) |path| break :d openUnresolved(arena, cwd, path, .@"global cache");
694 if (wasi) break :d openWasiPreopen(wasi_preopens, "/cache");
695 const path = introspect.resolveGlobalCacheDir(arena) catch |err| {
696 fatal("unable to resolve zig cache directory: {s}", .{@errorName(err)});
697 };
698 break :d openUnresolved(arena, cwd, path, .@"global cache");
699 };
700
701 const local_cache: Cache.Directory = switch (local_cache_strat) {
702 .override => |path| openUnresolved(arena, cwd, path, .@"local cache"),
703 .search => d: {
704 const maybe_path = introspect.resolveSuitableLocalCacheDir(arena, cwd) catch |err| {
705 fatal("unable to resolve zig cache directory: {s}", .{@errorName(err)});
706 };
707 const path = maybe_path orelse break :d global_cache;
708 break :d openUnresolved(arena, cwd, path, .@"local cache");
709 },
710 .global => global_cache,
711 };
712
713 if (std.mem.eql(u8, zig_lib.path orelse "", global_cache.path orelse "")) {
714 fatal("zig lib directory '{}' cannot be equal to global cache directory '{}'", .{ zig_lib, global_cache });
715 }
716 if (std.mem.eql(u8, zig_lib.path orelse "", local_cache.path orelse "")) {
717 fatal("zig lib directory '{}' cannot be equal to local cache directory '{}'", .{ zig_lib, local_cache });
718 }
719
720 return .{
721 .cwd = cwd,
722 .zig_lib = zig_lib,
723 .global_cache = global_cache,
724 .local_cache = local_cache,
725 };
726 }
727 fn openWasiPreopen(preopens: std.fs.wasi.Preopens, name: []const u8) Cache.Directory {
728 return .{
729 .path = if (std.mem.eql(u8, name, ".")) null else name,
730 .handle = .{
731 .fd = preopens.find(name) orelse fatal("WASI preopen not found: '{s}'", .{name}),
732 },
733 };
734 }
735 fn openUnresolved(arena: Allocator, cwd: []const u8, unresolved_path: []const u8, thing: enum { @"zig lib", @"global cache", @"local cache" }) Cache.Directory {
736 const path = introspect.resolvePath(arena, cwd, &.{unresolved_path}) catch |err| {
737 fatal("unable to resolve {s} directory: {s}", .{ @tagName(thing), @errorName(err) });
738 };
739 const nonempty_path = if (path.len == 0) "." else path;
740 const handle_or_err = switch (thing) {
741 .@"zig lib" => std.fs.cwd().openDir(nonempty_path, .{}),
742 .@"global cache", .@"local cache" => std.fs.cwd().makeOpenPath(nonempty_path, .{}),
743 };
744 return .{
745 .path = if (path.len == 0) null else path,
746 .handle = handle_or_err catch |err| {
747 const extra_str: []const u8 = e: {
748 if (thing == .@"global cache") switch (err) {
749 error.AccessDenied, error.ReadOnlyFileSystem => break :e "\n" ++
750 "If this location is not writable then consider specifying an alternative with " ++
751 "the ZIG_GLOBAL_CACHE_DIR environment variable or the --global-cache-dir option.",
752 else => {},
753 };
754 break :e "";
755 };
756 fatal("unable to open {s} directory '{s}': {s}{s}", .{ @tagName(thing), nonempty_path, @errorName(err), extra_str });
757 },
758 };
759 }
760};
761
315pub const default_stack_protector_buffer_size = target_util.default_stack_protector_buffer_size;762pub const default_stack_protector_buffer_size = target_util.default_stack_protector_buffer_size;
316pub const SemaError = Zcu.SemaError;763pub const SemaError = Zcu.SemaError;
317764
318pub const CrtFile = struct {765pub const CrtFile = struct {
319 lock: Cache.Lock,766 lock: Cache.Lock,
320 full_object_path: Path,767 full_object_path: Cache.Path,
321768
322 pub fn isObject(cf: CrtFile) bool {769 pub fn isObject(cf: CrtFile) bool {
323 return switch (classifyFileExt(cf.full_object_path.sub_path)) {770 return switch (classifyFileExt(cf.full_object_path.sub_path)) {
...@@ -430,7 +877,7 @@ pub const CObject = struct {...@@ -430,7 +877,7 @@ pub const CObject = struct {
430 new,877 new,
431 success: struct {878 success: struct {
432 /// The outputted result. `sub_path` owned by gpa.879 /// The outputted result. `sub_path` owned by gpa.
433 object_path: Path,880 object_path: Cache.Path,
434 /// This is a file system lock on the cache hash manifest representing this881 /// This is a file system lock on the cache hash manifest representing this
435 /// object. It prevents other invocations of the Zig compiler from interfering882 /// object. It prevents other invocations of the Zig compiler from interfering
436 /// with this object until released.883 /// with this object until released.
...@@ -854,7 +1301,7 @@ pub const MiscError = struct {...@@ -854,7 +1301,7 @@ pub const MiscError = struct {
854pub const EmitLoc = struct {1301pub const EmitLoc = struct {
855 /// If this is `null` it means the file will be output to the cache directory.1302 /// If this is `null` it means the file will be output to the cache directory.
856 /// When provided, both the open file handle and the path name must outlive the `Compilation`.1303 /// When provided, both the open file handle and the path name must outlive the `Compilation`.
857 directory: ?Compilation.Directory,1304 directory: ?Cache.Directory,
858 /// This may not have sub-directories in it.1305 /// This may not have sub-directories in it.
859 basename: []const u8,1306 basename: []const u8,
860};1307};
...@@ -977,7 +1424,7 @@ const CacheUse = union(CacheMode) {...@@ -977,7 +1424,7 @@ const CacheUse = union(CacheMode) {
977 implib_sub_path: ?[]u8,1424 implib_sub_path: ?[]u8,
978 docs_sub_path: ?[]u8,1425 docs_sub_path: ?[]u8,
979 lf_open_opts: link.File.OpenOptions,1426 lf_open_opts: link.File.OpenOptions,
980 tmp_artifact_directory: ?Directory,1427 tmp_artifact_directory: ?Cache.Directory,
981 /// Prevents other processes from clobbering files in the output directory.1428 /// Prevents other processes from clobbering files in the output directory.
982 lock: ?Cache.Lock,1429 lock: ?Cache.Lock,
9831430
...@@ -997,7 +1444,7 @@ const CacheUse = union(CacheMode) {...@@ -997,7 +1444,7 @@ const CacheUse = union(CacheMode) {
9971444
998 const Incremental = struct {1445 const Incremental = struct {
999 /// Where build artifacts and incremental compilation metadata serialization go.1446 /// Where build artifacts and incremental compilation metadata serialization go.
1000 artifact_directory: Compilation.Directory,1447 artifact_directory: Cache.Directory,
1001 };1448 };
10021449
1003 fn deinit(cu: CacheUse) void {1450 fn deinit(cu: CacheUse) void {
...@@ -1013,9 +1460,7 @@ const CacheUse = union(CacheMode) {...@@ -1013,9 +1460,7 @@ const CacheUse = union(CacheMode) {
1013};1460};
10141461
1015pub const CreateOptions = struct {1462pub const CreateOptions = struct {
1016 zig_lib_directory: Directory,1463 dirs: Directories,
1017 local_cache_directory: Directory,
1018 global_cache_directory: Directory,
1019 thread_pool: *ThreadPool,1464 thread_pool: *ThreadPool,
1020 self_exe_path: ?[]const u8 = null,1465 self_exe_path: ?[]const u8 = null,
10211466
...@@ -1059,7 +1504,7 @@ pub const CreateOptions = struct {...@@ -1059,7 +1504,7 @@ pub const CreateOptions = struct {
1059 /// This field is intended to be removed.1504 /// This field is intended to be removed.
1060 /// The ELF implementation no longer uses this data, however the MachO and COFF1505 /// The ELF implementation no longer uses this data, however the MachO and COFF
1061 /// implementations still do.1506 /// implementations still do.
1062 lib_directories: []const Directory = &.{},1507 lib_directories: []const Cache.Directory = &.{},
1063 rpath_list: []const []const u8 = &[0][]const u8{},1508 rpath_list: []const []const u8 = &[0][]const u8{},
1064 symbol_wrap_set: std.StringArrayHashMapUnmanaged(void) = .empty,1509 symbol_wrap_set: std.StringArrayHashMapUnmanaged(void) = .empty,
1065 c_source_files: []const CSourceFile = &.{},1510 c_source_files: []const CSourceFile = &.{},
...@@ -1195,68 +1640,35 @@ pub const CreateOptions = struct {...@@ -1195,68 +1640,35 @@ pub const CreateOptions = struct {
1195};1640};
11961641
1197fn addModuleTableToCacheHash(1642fn addModuleTableToCacheHash(
1198 gpa: Allocator,1643 zcu: *Zcu,
1199 arena: Allocator,1644 arena: Allocator,
1200 hash: *Cache.HashHelper,1645 hash: *Cache.HashHelper,
1201 root_mod: *Package.Module,
1202 main_mod: *Package.Module,
1203 hash_type: union(enum) { path_bytes, files: *Cache.Manifest },1646 hash_type: union(enum) { path_bytes, files: *Cache.Manifest },
1204) (error{OutOfMemory} || std.process.GetCwdError)!void {1647) error{
1205 var seen_table: std.AutoArrayHashMapUnmanaged(*Package.Module, void) = .empty;1648 OutOfMemory,
1206 defer seen_table.deinit(gpa);1649 Unexpected,
12071650 CurrentWorkingDirectoryUnlinked,
1208 // root_mod and main_mod may be the same pointer. In fact they usually are.1651}!void {
1209 // However in the case of `zig test` or `zig build` they will be different,1652 assert(zcu.module_roots.count() != 0); // module_roots is populated
1210 // and it's possible for one to not reference the other via the import table.1653
1211 try seen_table.put(gpa, root_mod, {});1654 for (zcu.module_roots.keys(), zcu.module_roots.values()) |mod, opt_mod_root_file| {
1212 try seen_table.put(gpa, main_mod, {});1655 if (mod == zcu.std_mod) continue; // redundant
12131656 if (opt_mod_root_file.unwrap()) |mod_root_file| {
1214 const SortByName = struct {1657 if (zcu.fileByIndex(mod_root_file).is_builtin) continue; // redundant
1215 has_builtin: bool,
1216 names: []const []const u8,
1217
1218 pub fn lessThan(ctx: @This(), lhs: usize, rhs: usize) bool {
1219 return if (ctx.has_builtin and (lhs == 0 or rhs == 0))
1220 lhs < rhs
1221 else
1222 mem.lessThan(u8, ctx.names[lhs], ctx.names[rhs]);
1223 }1658 }
1224 };
1225
1226 var i: usize = 0;
1227 while (i < seen_table.count()) : (i += 1) {
1228 const mod = seen_table.keys()[i];
1229 if (mod.isBuiltin()) {
1230 // Skip builtin.zig; it is useless as an input, and we don't want to
1231 // have to write it before checking for a cache hit.
1232 continue;
1233 }
1234
1235 cache_helpers.addModule(hash, mod);1659 cache_helpers.addModule(hash, mod);
1236
1237 switch (hash_type) {1660 switch (hash_type) {
1238 .path_bytes => {1661 .path_bytes => {
1239 hash.addBytes(mod.root_src_path);1662 hash.add(mod.root.root);
1240 hash.addOptionalBytes(mod.root.root_dir.path);
1241 hash.addBytes(mod.root.sub_path);1663 hash.addBytes(mod.root.sub_path);
1664 hash.addBytes(mod.root_src_path);
1242 },1665 },
1243 .files => |man| if (mod.root_src_path.len != 0) {1666 .files => |man| if (mod.root_src_path.len != 0) {
1244 const pkg_zig_file = try mod.root.joinString(arena, mod.root_src_path);1667 const root_src_path = try mod.root.toCachePath(zcu.comp.dirs).join(arena, mod.root_src_path);
1245 _ = try man.addFile(pkg_zig_file, null);1668 _ = try man.addFilePath(root_src_path, null);
1246 },1669 },
1247 }1670 }
1248
1249 mod.deps.sortUnstable(SortByName{
1250 .has_builtin = mod.deps.count() >= 1 and
1251 mod.deps.values()[0].isBuiltin(),
1252 .names = mod.deps.keys(),
1253 });
1254
1255 hash.addListOfBytes(mod.deps.keys());1671 hash.addListOfBytes(mod.deps.keys());
1256
1257 const deps = mod.deps.values();
1258 try seen_table.ensureUnusedCapacity(gpa, deps.len);
1259 for (deps) |dep| seen_table.putAssumeCapacity(dep, {});
1260 }1672 }
1261}1673}
12621674
...@@ -1310,7 +1722,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil...@@ -1310,7 +1722,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
13101722
1311 const libc_dirs = try std.zig.LibCDirs.detect(1723 const libc_dirs = try std.zig.LibCDirs.detect(
1312 arena,1724 arena,
1313 options.zig_lib_directory.path.?,1725 options.dirs.zig_lib.path.?,
1314 options.root_mod.resolved_target.result,1726 options.root_mod.resolved_target.result,
1315 options.root_mod.resolved_target.is_native_abi,1727 options.root_mod.resolved_target.is_native_abi,
1316 link_libc,1728 link_libc,
...@@ -1332,11 +1744,8 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil...@@ -1332,11 +1744,8 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
1332 // For objects, this mechanism relies on essentially `_ = @import("compiler-rt");`1744 // For objects, this mechanism relies on essentially `_ = @import("compiler-rt");`
1333 // injected into the object.1745 // injected into the object.
1334 const compiler_rt_mod = try Package.Module.create(arena, .{1746 const compiler_rt_mod = try Package.Module.create(arena, .{
1335 .global_cache_directory = options.global_cache_directory,
1336 .paths = .{1747 .paths = .{
1337 .root = .{1748 .root = .zig_lib_root,
1338 .root_dir = options.zig_lib_directory,
1339 },
1340 .root_src_path = "compiler_rt.zig",1749 .root_src_path = "compiler_rt.zig",
1341 },1750 },
1342 .fully_qualified_name = "compiler_rt",1751 .fully_qualified_name = "compiler_rt",
...@@ -1348,8 +1757,6 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil...@@ -1348,8 +1757,6 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
1348 },1757 },
1349 .global = options.config,1758 .global = options.config,
1350 .parent = options.root_mod,1759 .parent = options.root_mod,
1351 .builtin_mod = options.root_mod.getBuiltinDependency(),
1352 .builtin_modules = null, // `builtin_mod` is set
1353 });1760 });
1354 try options.root_mod.deps.putNoClobber(arena, "compiler_rt", compiler_rt_mod);1761 try options.root_mod.deps.putNoClobber(arena, "compiler_rt", compiler_rt_mod);
1355 }1762 }
...@@ -1369,11 +1776,8 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil...@@ -1369,11 +1776,8 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
13691776
1370 if (ubsan_rt_strat == .zcu) {1777 if (ubsan_rt_strat == .zcu) {
1371 const ubsan_rt_mod = try Package.Module.create(arena, .{1778 const ubsan_rt_mod = try Package.Module.create(arena, .{
1372 .global_cache_directory = options.global_cache_directory,
1373 .paths = .{1779 .paths = .{
1374 .root = .{1780 .root = .zig_lib_root,
1375 .root_dir = options.zig_lib_directory,
1376 },
1377 .root_src_path = "ubsan_rt.zig",1781 .root_src_path = "ubsan_rt.zig",
1378 },1782 },
1379 .fully_qualified_name = "ubsan_rt",1783 .fully_qualified_name = "ubsan_rt",
...@@ -1381,8 +1785,6 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil...@@ -1381,8 +1785,6 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
1381 .inherited = .{},1785 .inherited = .{},
1382 .global = options.config,1786 .global = options.config,
1383 .parent = options.root_mod,1787 .parent = options.root_mod,
1384 .builtin_mod = options.root_mod.getBuiltinDependency(),
1385 .builtin_modules = null, // `builtin_mod` is set
1386 });1788 });
1387 try options.root_mod.deps.putNoClobber(arena, "ubsan_rt", ubsan_rt_mod);1789 try options.root_mod.deps.putNoClobber(arena, "ubsan_rt", ubsan_rt_mod);
1388 }1790 }
...@@ -1415,13 +1817,13 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil...@@ -1415,13 +1817,13 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
1415 const cache = try arena.create(Cache);1817 const cache = try arena.create(Cache);
1416 cache.* = .{1818 cache.* = .{
1417 .gpa = gpa,1819 .gpa = gpa,
1418 .manifest_dir = try options.local_cache_directory.handle.makeOpenPath("h", .{}),1820 .manifest_dir = try options.dirs.local_cache.handle.makeOpenPath("h", .{}),
1419 };1821 };
1420 // These correspond to std.zig.Server.Message.PathPrefix.1822 // These correspond to std.zig.Server.Message.PathPrefix.
1421 cache.addPrefix(.{ .path = null, .handle = std.fs.cwd() });1823 cache.addPrefix(.{ .path = null, .handle = std.fs.cwd() });
1422 cache.addPrefix(options.zig_lib_directory);1824 cache.addPrefix(options.dirs.zig_lib);
1423 cache.addPrefix(options.local_cache_directory);1825 cache.addPrefix(options.dirs.local_cache);
1424 cache.addPrefix(options.global_cache_directory);1826 cache.addPrefix(options.dirs.global_cache);
1425 errdefer cache.manifest_dir.close();1827 errdefer cache.manifest_dir.close();
14261828
1427 // This is shared hasher state common to zig source and all C source files.1829 // This is shared hasher state common to zig source and all C source files.
...@@ -1458,26 +1860,22 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil...@@ -1458,26 +1860,22 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
1458 // to redundantly happen for each AstGen operation.1860 // to redundantly happen for each AstGen operation.
1459 const zir_sub_dir = "z";1861 const zir_sub_dir = "z";
14601862
1461 var local_zir_dir = try options.local_cache_directory.handle.makeOpenPath(zir_sub_dir, .{});1863 var local_zir_dir = try options.dirs.local_cache.handle.makeOpenPath(zir_sub_dir, .{});
1462 errdefer local_zir_dir.close();1864 errdefer local_zir_dir.close();
1463 const local_zir_cache: Directory = .{1865 const local_zir_cache: Cache.Directory = .{
1464 .handle = local_zir_dir,1866 .handle = local_zir_dir,
1465 .path = try options.local_cache_directory.join(arena, &[_][]const u8{zir_sub_dir}),1867 .path = try options.dirs.local_cache.join(arena, &.{zir_sub_dir}),
1466 };1868 };
1467 var global_zir_dir = try options.global_cache_directory.handle.makeOpenPath(zir_sub_dir, .{});1869 var global_zir_dir = try options.dirs.global_cache.handle.makeOpenPath(zir_sub_dir, .{});
1468 errdefer global_zir_dir.close();1870 errdefer global_zir_dir.close();
1469 const global_zir_cache: Directory = .{1871 const global_zir_cache: Cache.Directory = .{
1470 .handle = global_zir_dir,1872 .handle = global_zir_dir,
1471 .path = try options.global_cache_directory.join(arena, &[_][]const u8{zir_sub_dir}),1873 .path = try options.dirs.global_cache.join(arena, &.{zir_sub_dir}),
1472 };1874 };
14731875
1474 const std_mod = options.std_mod orelse try Package.Module.create(arena, .{1876 const std_mod = options.std_mod orelse try Package.Module.create(arena, .{
1475 .global_cache_directory = options.global_cache_directory,
1476 .paths = .{1877 .paths = .{
1477 .root = .{1878 .root = try .fromRoot(arena, options.dirs, .zig_lib, "std"),
1478 .root_dir = options.zig_lib_directory,
1479 .sub_path = "std",
1480 },
1481 .root_src_path = "std.zig",1879 .root_src_path = "std.zig",
1482 },1880 },
1483 .fully_qualified_name = "std",1881 .fully_qualified_name = "std",
...@@ -1485,8 +1883,6 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil...@@ -1485,8 +1883,6 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
1485 .inherited = .{},1883 .inherited = .{},
1486 .global = options.config,1884 .global = options.config,
1487 .parent = options.root_mod,1885 .parent = options.root_mod,
1488 .builtin_mod = options.root_mod.getBuiltinDependency(),
1489 .builtin_modules = null, // `builtin_mod` is set
1490 });1886 });
14911887
1492 const zcu = try arena.create(Zcu);1888 const zcu = try arena.create(Zcu);
...@@ -1522,16 +1918,13 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil...@@ -1522,16 +1918,13 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
1522 .docs_emit = null, // handled below1918 .docs_emit = null, // handled below
1523 .root_mod = options.root_mod,1919 .root_mod = options.root_mod,
1524 .config = options.config,1920 .config = options.config,
1525 .zig_lib_directory = options.zig_lib_directory,1921 .dirs = options.dirs,
1526 .local_cache_directory = options.local_cache_directory,
1527 .global_cache_directory = options.global_cache_directory,
1528 .emit_asm = options.emit_asm,1922 .emit_asm = options.emit_asm,
1529 .emit_llvm_ir = options.emit_llvm_ir,1923 .emit_llvm_ir = options.emit_llvm_ir,
1530 .emit_llvm_bc = options.emit_llvm_bc,1924 .emit_llvm_bc = options.emit_llvm_bc,
1531 .work_queues = @splat(.init(gpa)),1925 .work_queues = @splat(.init(gpa)),
1532 .c_object_work_queue = std.fifo.LinearFifo(*CObject, .Dynamic).init(gpa),1926 .c_object_work_queue = std.fifo.LinearFifo(*CObject, .Dynamic).init(gpa),
1533 .win32_resource_work_queue = if (dev.env.supports(.win32_resource)) std.fifo.LinearFifo(*Win32Resource, .Dynamic).init(gpa) else .{},1927 .win32_resource_work_queue = if (dev.env.supports(.win32_resource)) std.fifo.LinearFifo(*Win32Resource, .Dynamic).init(gpa) else .{},
1534 .astgen_work_queue = std.fifo.LinearFifo(Zcu.File.Index, .Dynamic).init(gpa),
1535 .c_source_files = options.c_source_files,1928 .c_source_files = options.c_source_files,
1536 .rc_source_files = options.rc_source_files,1929 .rc_source_files = options.rc_source_files,
1537 .cache_parent = cache,1930 .cache_parent = cache,
...@@ -1572,9 +1965,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil...@@ -1572,9 +1965,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
1572 .framework_dirs = options.framework_dirs,1965 .framework_dirs = options.framework_dirs,
1573 .llvm_opt_bisect_limit = options.llvm_opt_bisect_limit,1966 .llvm_opt_bisect_limit = options.llvm_opt_bisect_limit,
1574 .skip_linker_dependencies = options.skip_linker_dependencies,1967 .skip_linker_dependencies = options.skip_linker_dependencies,
1575 .queued_jobs = .{1968 .queued_jobs = .{},
1576 .update_builtin_zig = have_zcu,
1577 },
1578 .function_sections = options.function_sections,1969 .function_sections = options.function_sections,
1579 .data_sections = options.data_sections,1970 .data_sections = options.data_sections,
1580 .native_system_include_paths = options.native_system_include_paths,1971 .native_system_include_paths = options.native_system_include_paths,
...@@ -1596,6 +1987,13 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil...@@ -1596,6 +1987,13 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
1596 comp.config.any_sanitize_c = any_sanitize_c;1987 comp.config.any_sanitize_c = any_sanitize_c;
1597 comp.config.any_fuzz = any_fuzz;1988 comp.config.any_fuzz = any_fuzz;
15981989
1990 if (opt_zcu) |zcu| {
1991 // Populate `zcu.module_roots`.
1992 const pt: Zcu.PerThread = .activate(zcu, .main);
1993 defer pt.deactivate();
1994 try pt.populateModuleRootTable();
1995 }
1996
1599 const lf_open_opts: link.File.OpenOptions = .{1997 const lf_open_opts: link.File.OpenOptions = .{
1600 .linker_script = options.linker_script,1998 .linker_script = options.linker_script,
1601 .z_nodelete = options.linker_z_nodelete,1999 .z_nodelete = options.linker_z_nodelete,
...@@ -1686,7 +2084,11 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil...@@ -1686,7 +2084,11 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
1686 // do want to namespace different source file names because they are2084 // do want to namespace different source file names because they are
1687 // likely different compilations and therefore this would be likely to2085 // likely different compilations and therefore this would be likely to
1688 // cause cache hits.2086 // cause cache hits.
1689 try addModuleTableToCacheHash(gpa, arena, &hash, options.root_mod, main_mod, .path_bytes);2087 if (comp.zcu) |zcu| {
2088 try addModuleTableToCacheHash(zcu, arena, &hash, .path_bytes);
2089 } else {
2090 cache_helpers.addModule(&hash, options.root_mod);
2091 }
16902092
1691 // In the case of incremental cache mode, this `artifact_directory`2093 // In the case of incremental cache mode, this `artifact_directory`
1692 // is computed based on a hash of non-linker inputs, and it is where all2094 // is computed based on a hash of non-linker inputs, and it is where all
...@@ -1695,11 +2097,11 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil...@@ -1695,11 +2097,11 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
1695 const digest = hash.final();2097 const digest = hash.final();
16962098
1697 const artifact_sub_dir = "o" ++ std.fs.path.sep_str ++ digest;2099 const artifact_sub_dir = "o" ++ std.fs.path.sep_str ++ digest;
1698 var artifact_dir = try options.local_cache_directory.handle.makeOpenPath(artifact_sub_dir, .{});2100 var artifact_dir = try options.dirs.local_cache.handle.makeOpenPath(artifact_sub_dir, .{});
1699 errdefer artifact_dir.close();2101 errdefer artifact_dir.close();
1700 const artifact_directory: Directory = .{2102 const artifact_directory: Cache.Directory = .{
1701 .handle = artifact_dir,2103 .handle = artifact_dir,
1702 .path = try options.local_cache_directory.join(arena, &[_][]const u8{artifact_sub_dir}),2104 .path = try options.dirs.local_cache.join(arena, &.{artifact_sub_dir}),
1703 };2105 };
17042106
1705 const incremental = try arena.create(CacheUse.Incremental);2107 const incremental = try arena.create(CacheUse.Incremental);
...@@ -1709,7 +2111,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil...@@ -1709,7 +2111,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
1709 comp.cache_use = .{ .incremental = incremental };2111 comp.cache_use = .{ .incremental = incremental };
17102112
1711 if (options.emit_bin) |emit_bin| {2113 if (options.emit_bin) |emit_bin| {
1712 const emit: Path = .{2114 const emit: Cache.Path = .{
1713 .root_dir = emit_bin.directory orelse artifact_directory,2115 .root_dir = emit_bin.directory orelse artifact_directory,
1714 .sub_path = emit_bin.basename,2116 .sub_path = emit_bin.basename,
1715 };2117 };
...@@ -1998,10 +2400,10 @@ pub fn destroy(comp: *Compilation) void {...@@ -1998,10 +2400,10 @@ pub fn destroy(comp: *Compilation) void {
1998 if (comp.bin_file) |lf| lf.destroy();2400 if (comp.bin_file) |lf| lf.destroy();
1999 if (comp.zcu) |zcu| zcu.deinit();2401 if (comp.zcu) |zcu| zcu.deinit();
2000 comp.cache_use.deinit();2402 comp.cache_use.deinit();
2403
2001 for (comp.work_queues) |work_queue| work_queue.deinit();2404 for (comp.work_queues) |work_queue| work_queue.deinit();
2002 comp.c_object_work_queue.deinit();2405 comp.c_object_work_queue.deinit();
2003 comp.win32_resource_work_queue.deinit();2406 comp.win32_resource_work_queue.deinit();
2004 comp.astgen_work_queue.deinit();
20052407
2006 comp.windows_libs.deinit(gpa);2408 comp.windows_libs.deinit(gpa);
20072409
...@@ -2207,15 +2609,15 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void {...@@ -2207,15 +2609,15 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void {
2207 log.debug("CacheMode.whole cache miss for {s}", .{comp.root_name});2609 log.debug("CacheMode.whole cache miss for {s}", .{comp.root_name});
22082610
2209 // Compile the artifacts to a temporary directory.2611 // Compile the artifacts to a temporary directory.
2210 const tmp_artifact_directory: Directory = d: {2612 const tmp_artifact_directory: Cache.Directory = d: {
2211 const s = std.fs.path.sep_str;2613 const s = std.fs.path.sep_str;
2212 tmp_dir_rand_int = std.crypto.random.int(u64);2614 tmp_dir_rand_int = std.crypto.random.int(u64);
2213 const tmp_dir_sub_path = "tmp" ++ s ++ std.fmt.hex(tmp_dir_rand_int);2615 const tmp_dir_sub_path = "tmp" ++ s ++ std.fmt.hex(tmp_dir_rand_int);
22142616
2215 const path = try comp.local_cache_directory.join(gpa, &.{tmp_dir_sub_path});2617 const path = try comp.dirs.local_cache.join(gpa, &.{tmp_dir_sub_path});
2216 errdefer gpa.free(path);2618 errdefer gpa.free(path);
22172619
2218 const handle = try comp.local_cache_directory.handle.makeOpenPath(tmp_dir_sub_path, .{});2620 const handle = try comp.dirs.local_cache.handle.makeOpenPath(tmp_dir_sub_path, .{});
2219 errdefer handle.close();2621 errdefer handle.close();
22202622
2221 break :d .{2623 break :d .{
...@@ -2243,7 +2645,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void {...@@ -2243,7 +2645,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void {
2243 }2645 }
22442646
2245 if (whole.bin_sub_path) |sub_path| {2647 if (whole.bin_sub_path) |sub_path| {
2246 const emit: Path = .{2648 const emit: Cache.Path = .{
2247 .root_dir = tmp_artifact_directory,2649 .root_dir = tmp_artifact_directory,
2248 .sub_path = std.fs.path.basename(sub_path),2650 .sub_path = std.fs.path.basename(sub_path),
2249 };2651 };
...@@ -2265,26 +2667,22 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void {...@@ -2265,26 +2667,22 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void {
2265 // For compiling C objects, we rely on the cache hash system to avoid duplicating work.2667 // For compiling C objects, we rely on the cache hash system to avoid duplicating work.
2266 // Add a Job for each C object.2668 // Add a Job for each C object.
2267 try comp.c_object_work_queue.ensureUnusedCapacity(comp.c_object_table.count());2669 try comp.c_object_work_queue.ensureUnusedCapacity(comp.c_object_table.count());
2268 for (comp.c_object_table.keys()) |key| {2670 for (comp.c_object_table.keys()) |c_object| {
2269 comp.c_object_work_queue.writeItemAssumeCapacity(key);2671 comp.c_object_work_queue.writeItemAssumeCapacity(c_object);
2270 }2672 try comp.appendFileSystemInput(try .fromUnresolved(arena, comp.dirs, &.{c_object.src.src_path}));
2271 if (comp.file_system_inputs) |fsi| {
2272 for (comp.c_object_table.keys()) |c_object| {
2273 try comp.appendFileSystemInput(fsi, Cache.Path.cwd(), c_object.src.src_path);
2274 }
2275 }2673 }
22762674
2277 // For compiling Win32 resources, we rely on the cache hash system to avoid duplicating work.2675 // For compiling Win32 resources, we rely on the cache hash system to avoid duplicating work.
2278 // Add a Job for each Win32 resource file.2676 // Add a Job for each Win32 resource file.
2279 try comp.win32_resource_work_queue.ensureUnusedCapacity(comp.win32_resource_table.count());2677 try comp.win32_resource_work_queue.ensureUnusedCapacity(comp.win32_resource_table.count());
2280 for (comp.win32_resource_table.keys()) |key| {2678 for (comp.win32_resource_table.keys()) |win32_resource| {
2281 comp.win32_resource_work_queue.writeItemAssumeCapacity(key);2679 comp.win32_resource_work_queue.writeItemAssumeCapacity(win32_resource);
2282 }2680 switch (win32_resource.src) {
2283 if (comp.file_system_inputs) |fsi| {2681 .rc => |f| {
2284 for (comp.win32_resource_table.keys()) |win32_resource| switch (win32_resource.src) {2682 try comp.appendFileSystemInput(try .fromUnresolved(arena, comp.dirs, &.{f.src_path}));
2285 .rc => |f| try comp.appendFileSystemInput(fsi, Cache.Path.cwd(), f.src_path),2683 },
2286 .manifest => continue,2684 .manifest => {},
2287 };2685 }
2288 }2686 }
22892687
2290 if (comp.zcu) |zcu| {2688 if (comp.zcu) |zcu| {
...@@ -2293,69 +2691,26 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void {...@@ -2293,69 +2691,26 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void {
22932691
2294 zcu.skip_analysis_this_update = false;2692 zcu.skip_analysis_this_update = false;
22952693
2296 // Make sure std.zig is inside the import_table. We unconditionally need2694 // TODO: doing this in `resolveReferences` later could avoid adding inputs for dead embedfiles. Investigate!
2297 // it for start.zig.2695 for (zcu.embed_table.keys()) |embed_file| {
2298 const std_mod = zcu.std_mod;2696 try comp.appendFileSystemInput(embed_file.path);
2299 _ = try pt.importPkg(std_mod);
2300
2301 // Normally we rely on importing std to in turn import the root source file
2302 // in the start code, but when using the stage1 backend that won't happen,
2303 // so in order to run AstGen on the root source file we put it into the
2304 // import_table here.
2305 // Likewise, in the case of `zig test`, the test runner is the root source file,
2306 // and so there is nothing to import the main file.
2307 if (comp.config.is_test) {
2308 _ = try pt.importPkg(zcu.main_mod);
2309 }
2310
2311 if (zcu.root_mod.deps.get("ubsan_rt")) |ubsan_rt_mod| {
2312 _ = try pt.importPkg(ubsan_rt_mod);
2313 }
2314
2315 if (zcu.root_mod.deps.get("compiler_rt")) |compiler_rt_mod| {
2316 _ = try pt.importPkg(compiler_rt_mod);
2317 }
2318
2319 // Put a work item in for every known source file to detect if
2320 // it changed, and, if so, re-compute ZIR and then queue the job
2321 // to update it.
2322 try comp.astgen_work_queue.ensureUnusedCapacity(zcu.import_table.count());
2323 for (zcu.import_table.values()) |file_index| {
2324 if (zcu.fileByIndex(file_index).mod.isBuiltin()) continue;
2325 comp.astgen_work_queue.writeItemAssumeCapacity(file_index);
2326 }
2327 if (comp.file_system_inputs) |fsi| {
2328 for (zcu.import_table.values()) |file_index| {
2329 const file = zcu.fileByIndex(file_index);
2330 try comp.appendFileSystemInput(fsi, file.mod.root, file.sub_file_path);
2331 }
2332 }
2333
2334 if (comp.file_system_inputs) |fsi| {
2335 const ip = &zcu.intern_pool;
2336 for (zcu.embed_table.values()) |embed_file| {
2337 const sub_file_path = embed_file.sub_file_path.toSlice(ip);
2338 try comp.appendFileSystemInput(fsi, embed_file.owner.root, sub_file_path);
2339 }
2340 }2697 }
23412698
2342 zcu.analysis_roots.clear();2699 zcu.analysis_roots.clear();
23432700
2344 try comp.queueJob(.{ .analyze_mod = std_mod });2701 zcu.analysis_roots.appendAssumeCapacity(zcu.std_mod);
2345 zcu.analysis_roots.appendAssumeCapacity(std_mod);
23462702
2347 if (comp.config.is_test and zcu.main_mod != std_mod) {2703 // Normally we rely on importing std to in turn import the root source file in the start code.
2348 try comp.queueJob(.{ .analyze_mod = zcu.main_mod });2704 // However, the main module is distinct from the root module in tests, so that won't happen there.
2705 if (comp.config.is_test and zcu.main_mod != zcu.std_mod) {
2349 zcu.analysis_roots.appendAssumeCapacity(zcu.main_mod);2706 zcu.analysis_roots.appendAssumeCapacity(zcu.main_mod);
2350 }2707 }
23512708
2352 if (zcu.root_mod.deps.get("compiler_rt")) |compiler_rt_mod| {2709 if (zcu.root_mod.deps.get("compiler_rt")) |compiler_rt_mod| {
2353 try comp.queueJob(.{ .analyze_mod = compiler_rt_mod });
2354 zcu.analysis_roots.appendAssumeCapacity(compiler_rt_mod);2710 zcu.analysis_roots.appendAssumeCapacity(compiler_rt_mod);
2355 }2711 }
23562712
2357 if (zcu.root_mod.deps.get("ubsan_rt")) |ubsan_rt_mod| {2713 if (zcu.root_mod.deps.get("ubsan_rt")) |ubsan_rt_mod| {
2358 try comp.queueJob(.{ .analyze_mod = ubsan_rt_mod });
2359 zcu.analysis_roots.appendAssumeCapacity(ubsan_rt_mod);2714 zcu.analysis_roots.appendAssumeCapacity(ubsan_rt_mod);
2360 }2715 }
2361 }2716 }
...@@ -2451,13 +2806,13 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void {...@@ -2451,13 +2806,13 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void {
2451 break :w .no;2806 break :w .no;
2452 };2807 };
24532808
2454 renameTmpIntoCache(comp.local_cache_directory, tmp_dir_sub_path, o_sub_path) catch |err| {2809 renameTmpIntoCache(comp.dirs.local_cache, tmp_dir_sub_path, o_sub_path) catch |err| {
2455 return comp.setMiscFailure(2810 return comp.setMiscFailure(
2456 .rename_results,2811 .rename_results,
2457 "failed to rename compilation results ('{}{s}') into local cache ('{}{s}'): {s}",2812 "failed to rename compilation results ('{}{s}') into local cache ('{}{s}'): {s}",
2458 .{2813 .{
2459 comp.local_cache_directory, tmp_dir_sub_path,2814 comp.dirs.local_cache, tmp_dir_sub_path,
2460 comp.local_cache_directory, o_sub_path,2815 comp.dirs.local_cache, o_sub_path,
2461 @errorName(err),2816 @errorName(err),
2462 },2817 },
2463 );2818 );
...@@ -2470,7 +2825,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void {...@@ -2470,7 +2825,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void {
2470 // references object file paths.2825 // references object file paths.
2471 if (comp.bin_file) |lf| {2826 if (comp.bin_file) |lf| {
2472 lf.emit = .{2827 lf.emit = .{
2473 .root_dir = comp.local_cache_directory,2828 .root_dir = comp.dirs.local_cache,
2474 .sub_path = whole.bin_sub_path.?,2829 .sub_path = whole.bin_sub_path.?,
2475 };2830 };
24762831
...@@ -2486,7 +2841,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void {...@@ -2486,7 +2841,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void {
2486 }2841 }
24872842
2488 try flush(comp, arena, .{2843 try flush(comp, arena, .{
2489 .root_dir = comp.local_cache_directory,2844 .root_dir = comp.dirs.local_cache,
2490 .sub_path = o_sub_path,2845 .sub_path = o_sub_path,
2491 }, .main, main_progress_node);2846 }, .main, main_progress_node);
24922847
...@@ -2515,34 +2870,36 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void {...@@ -2515,34 +2870,36 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void {
2515 }2870 }
2516}2871}
25172872
2518pub fn appendFileSystemInput(2873pub fn appendFileSystemInput(comp: *Compilation, path: Compilation.Path) Allocator.Error!void {
2519 comp: *Compilation,
2520 file_system_inputs: *std.ArrayListUnmanaged(u8),
2521 root: Cache.Path,
2522 sub_file_path: []const u8,
2523) Allocator.Error!void {
2524 const gpa = comp.gpa;2874 const gpa = comp.gpa;
2875 const fsi = comp.file_system_inputs orelse return;
2525 const prefixes = comp.cache_parent.prefixes();2876 const prefixes = comp.cache_parent.prefixes();
2526 try file_system_inputs.ensureUnusedCapacity(gpa, root.sub_path.len + sub_file_path.len + 3);2877
2527 if (file_system_inputs.items.len > 0) file_system_inputs.appendAssumeCapacity(0);2878 const want_prefix_dir: Cache.Directory = switch (path.root) {
2528 for (prefixes, 1..) |prefix_directory, i| {2879 .zig_lib => comp.dirs.zig_lib,
2529 if (prefix_directory.eql(root.root_dir)) {2880 .global_cache => comp.dirs.global_cache,
2530 file_system_inputs.appendAssumeCapacity(@intCast(i));2881 .local_cache => comp.dirs.local_cache,
2531 if (root.sub_path.len > 0) {2882 .none => .cwd(),
2532 file_system_inputs.appendSliceAssumeCapacity(root.sub_path);2883 };
2533 file_system_inputs.appendAssumeCapacity(std.fs.path.sep);2884 const prefix: u8 = for (prefixes, 1..) |prefix_dir, i| {
2534 }2885 if (prefix_dir.eql(want_prefix_dir)) {
2535 file_system_inputs.appendSliceAssumeCapacity(sub_file_path);2886 break @intCast(i);
2536 return;
2537 }2887 }
2538 }2888 } else std.debug.panic(
2539 std.debug.panic("missing prefix directory: {}, {s}", .{ root, sub_file_path });2889 "missing prefix directory '{s}' ('{}') for '{s}'",
2890 .{ @tagName(path.root), want_prefix_dir, path.sub_path },
2891 );
2892
2893 try fsi.ensureUnusedCapacity(gpa, path.sub_path.len + 3);
2894 if (fsi.items.len > 0) fsi.appendAssumeCapacity(0);
2895 fsi.appendAssumeCapacity(prefix);
2896 fsi.appendSliceAssumeCapacity(path.sub_path);
2540}2897}
25412898
2542fn flush(2899fn flush(
2543 comp: *Compilation,2900 comp: *Compilation,
2544 arena: Allocator,2901 arena: Allocator,
2545 default_artifact_directory: Path,2902 default_artifact_directory: Cache.Path,
2546 tid: Zcu.PerThread.Id,2903 tid: Zcu.PerThread.Id,
2547 prog_node: std.Progress.Node,2904 prog_node: std.Progress.Node,
2548) !void {2905) !void {
...@@ -2574,7 +2931,7 @@ fn flush(...@@ -2574,7 +2931,7 @@ fn flush(
2574/// implementation at the bottom of this function.2931/// implementation at the bottom of this function.
2575/// This function is only called when CacheMode is `whole`.2932/// This function is only called when CacheMode is `whole`.
2576fn renameTmpIntoCache(2933fn renameTmpIntoCache(
2577 cache_directory: Compilation.Directory,2934 cache_directory: Cache.Directory,
2578 tmp_dir_sub_path: []const u8,2935 tmp_dir_sub_path: []const u8,
2579 o_sub_path: []const u8,2936 o_sub_path: []const u8,
2580) !void {2937) !void {
...@@ -2627,7 +2984,7 @@ fn wholeCacheModeSetBinFilePath(...@@ -2627,7 +2984,7 @@ fn wholeCacheModeSetBinFilePath(
2627 @memcpy(sub_path[digest_start..][0..digest.len], digest);2984 @memcpy(sub_path[digest_start..][0..digest.len], digest);
26282985
2629 comp.implib_emit = .{2986 comp.implib_emit = .{
2630 .root_dir = comp.local_cache_directory,2987 .root_dir = comp.dirs.local_cache,
2631 .sub_path = sub_path,2988 .sub_path = sub_path,
2632 };2989 };
2633 }2990 }
...@@ -2636,7 +2993,7 @@ fn wholeCacheModeSetBinFilePath(...@@ -2636,7 +2993,7 @@ fn wholeCacheModeSetBinFilePath(
2636 @memcpy(sub_path[digest_start..][0..digest.len], digest);2993 @memcpy(sub_path[digest_start..][0..digest.len], digest);
26372994
2638 comp.docs_emit = .{2995 comp.docs_emit = .{
2639 .root_dir = comp.local_cache_directory,2996 .root_dir = comp.dirs.local_cache,
2640 .sub_path = sub_path,2997 .sub_path = sub_path,
2641 };2998 };
2642 }2999 }
...@@ -2661,19 +3018,17 @@ fn addNonIncrementalStuffToCacheManifest(...@@ -2661,19 +3018,17 @@ fn addNonIncrementalStuffToCacheManifest(
2661 arena: Allocator,3018 arena: Allocator,
2662 man: *Cache.Manifest,3019 man: *Cache.Manifest,
2663) !void {3020) !void {
2664 const gpa = comp.gpa;
2665
2666 comptime assert(link_hash_implementation_version == 14);3021 comptime assert(link_hash_implementation_version == 14);
26673022
2668 if (comp.zcu) |mod| {3023 if (comp.zcu) |zcu| {
2669 try addModuleTableToCacheHash(gpa, arena, &man.hash, mod.root_mod, mod.main_mod, .{ .files = man });3024 try addModuleTableToCacheHash(zcu, arena, &man.hash, .{ .files = man });
26703025
2671 // Synchronize with other matching comments: ZigOnlyHashStuff3026 // Synchronize with other matching comments: ZigOnlyHashStuff
2672 man.hash.addListOfBytes(comp.test_filters);3027 man.hash.addListOfBytes(comp.test_filters);
2673 man.hash.addOptionalBytes(comp.test_name_prefix);3028 man.hash.addOptionalBytes(comp.test_name_prefix);
2674 man.hash.add(comp.skip_linker_dependencies);3029 man.hash.add(comp.skip_linker_dependencies);
2675 //man.hash.add(mod.emit_h != null);3030 //man.hash.add(zcu.emit_h != null);
2676 man.hash.add(mod.error_limit);3031 man.hash.add(zcu.error_limit);
2677 } else {3032 } else {
2678 cache_helpers.addModule(&man.hash, comp.root_mod);3033 cache_helpers.addModule(&man.hash, comp.root_mod);
2679 }3034 }
...@@ -2839,7 +3194,7 @@ fn emitOthers(comp: *Compilation) void {...@@ -2839,7 +3194,7 @@ fn emitOthers(comp: *Compilation) void {
2839pub fn emitLlvmObject(3194pub fn emitLlvmObject(
2840 comp: *Compilation,3195 comp: *Compilation,
2841 arena: Allocator,3196 arena: Allocator,
2842 default_artifact_directory: Path,3197 default_artifact_directory: Cache.Path,
2843 bin_emit_loc: ?EmitLoc,3198 bin_emit_loc: ?EmitLoc,
2844 llvm_object: LlvmObject.Ptr,3199 llvm_object: LlvmObject.Ptr,
2845 prog_node: std.Progress.Node,3200 prog_node: std.Progress.Node,
...@@ -2866,7 +3221,7 @@ pub fn emitLlvmObject(...@@ -2866,7 +3221,7 @@ pub fn emitLlvmObject(
28663221
2867fn resolveEmitLoc(3222fn resolveEmitLoc(
2868 arena: Allocator,3223 arena: Allocator,
2869 default_artifact_directory: Path,3224 default_artifact_directory: Cache.Path,
2870 opt_loc: ?EmitLoc,3225 opt_loc: ?EmitLoc,
2871) Allocator.Error!?[*:0]const u8 {3226) Allocator.Error!?[*:0]const u8 {
2872 const loc = opt_loc orelse return null;3227 const loc = opt_loc orelse return null;
...@@ -2877,132 +3232,6 @@ fn resolveEmitLoc(...@@ -2877,132 +3232,6 @@ fn resolveEmitLoc(
2877 return slice.ptr;3232 return slice.ptr;
2878}3233}
28793234
2880fn reportMultiModuleErrors(pt: Zcu.PerThread) !void {
2881 const zcu = pt.zcu;
2882 const gpa = zcu.gpa;
2883 const ip = &zcu.intern_pool;
2884 // Some cases can give you a whole bunch of multi-module errors, which it's not helpful to
2885 // print all of, so we'll cap the number of these to emit.
2886 var num_errors: u32 = 0;
2887 const max_errors = 5;
2888 // Attach the "some omitted" note to the final error message
2889 var last_err: ?*Zcu.ErrorMsg = null;
2890
2891 for (zcu.import_table.values()) |file_index| {
2892 const file = zcu.fileByIndex(file_index);
2893 if (!file.multi_pkg) continue;
2894
2895 num_errors += 1;
2896 if (num_errors > max_errors) continue;
2897
2898 const err = err_blk: {
2899 // Like with errors, let's cap the number of notes to prevent a huge error spew.
2900 const max_notes = 5;
2901 const omitted = file.references.items.len -| max_notes;
2902 const num_notes = file.references.items.len - omitted;
2903
2904 const notes = try gpa.alloc(Zcu.ErrorMsg, if (omitted > 0) num_notes + 1 else num_notes);
2905 errdefer gpa.free(notes);
2906
2907 for (notes[0..num_notes], file.references.items[0..num_notes], 0..) |*note, ref, i| {
2908 errdefer for (notes[0..i]) |*n| n.deinit(gpa);
2909 note.* = switch (ref) {
2910 .import => |import| try Zcu.ErrorMsg.init(
2911 gpa,
2912 .{
2913 .base_node_inst = try ip.trackZir(gpa, pt.tid, .{
2914 .file = import.file,
2915 .inst = .main_struct_inst,
2916 }),
2917 .offset = .{ .token_abs = import.token },
2918 },
2919 "imported from module {s}",
2920 .{zcu.fileByIndex(import.file).mod.fully_qualified_name},
2921 ),
2922 .root => |pkg| try Zcu.ErrorMsg.init(
2923 gpa,
2924 .{
2925 .base_node_inst = try ip.trackZir(gpa, pt.tid, .{
2926 .file = file_index,
2927 .inst = .main_struct_inst,
2928 }),
2929 .offset = .entire_file,
2930 },
2931 "root of module {s}",
2932 .{pkg.fully_qualified_name},
2933 ),
2934 };
2935 }
2936 errdefer for (notes[0..num_notes]) |*n| n.deinit(gpa);
2937
2938 if (omitted > 0) {
2939 notes[num_notes] = try Zcu.ErrorMsg.init(
2940 gpa,
2941 .{
2942 .base_node_inst = try ip.trackZir(gpa, pt.tid, .{
2943 .file = file_index,
2944 .inst = .main_struct_inst,
2945 }),
2946 .offset = .entire_file,
2947 },
2948 "{} more references omitted",
2949 .{omitted},
2950 );
2951 }
2952 errdefer if (omitted > 0) notes[num_notes].deinit(gpa);
2953
2954 const err = try Zcu.ErrorMsg.create(
2955 gpa,
2956 .{
2957 .base_node_inst = try ip.trackZir(gpa, pt.tid, .{
2958 .file = file_index,
2959 .inst = .main_struct_inst,
2960 }),
2961 .offset = .entire_file,
2962 },
2963 "file exists in multiple modules",
2964 .{},
2965 );
2966 err.notes = notes;
2967 break :err_blk err;
2968 };
2969 errdefer err.destroy(gpa);
2970 try zcu.failed_files.putNoClobber(gpa, file, err);
2971 last_err = err;
2972 }
2973
2974 // If we omitted any errors, add a note saying that
2975 if (num_errors > max_errors) {
2976 const err = last_err.?;
2977
2978 // There isn't really any meaningful place to put this note, so just attach it to the
2979 // last failed file
2980 var note = try Zcu.ErrorMsg.init(
2981 gpa,
2982 err.src_loc,
2983 "{} more errors omitted",
2984 .{num_errors - max_errors},
2985 );
2986 errdefer note.deinit(gpa);
2987
2988 const i = err.notes.len;
2989 err.notes = try gpa.realloc(err.notes, i + 1);
2990 err.notes[i] = note;
2991 }
2992
2993 // Now that we've reported the errors, we need to deal with
2994 // dependencies. Any file referenced by a multi_pkg file should also be
2995 // marked multi_pkg and have its status set to astgen_failure, as it's
2996 // ambiguous which package they should be analyzed as a part of. We need
2997 // to add this flag after reporting the errors however, as otherwise
2998 // we'd get an error for every single downstream file, which wouldn't be
2999 // very useful.
3000 for (zcu.import_table.values()) |file_index| {
3001 const file = zcu.fileByIndex(file_index);
3002 if (file.multi_pkg) file.recursiveMarkMultiPkg(pt);
3003 }
3004}
3005
3006/// Having the file open for writing is problematic as far as executing the3235/// Having the file open for writing is problematic as far as executing the
3007/// binary is concerned. This will remove the write flag, or close the file,3236/// binary is concerned. This will remove the write flag, or close the file,
3008/// or whatever is needed so that it can be executed.3237/// or whatever is needed so that it can be executed.
...@@ -3326,16 +3555,77 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle {...@@ -3326,16 +3555,77 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle {
3326 }3555 }
33273556
3328 if (comp.zcu) |zcu| zcu_errors: {3557 if (comp.zcu) |zcu| zcu_errors: {
3329 for (zcu.failed_files.keys(), zcu.failed_files.values()) |file, error_msg| {3558 if (zcu.multi_module_err != null) {
3559 try zcu.addFileInMultipleModulesError(&bundle);
3560 break :zcu_errors;
3561 }
3562 for (zcu.failed_imports.items) |failed| {
3563 assert(zcu.alive_files.contains(failed.file_index)); // otherwise it wouldn't have been added
3564 const file = zcu.fileByIndex(failed.file_index);
3565 const source = try file.getSource(zcu);
3566 const tree = try file.getTree(zcu);
3567 const start = tree.tokenStart(failed.import_token);
3568 const end = start + tree.tokenSlice(failed.import_token).len;
3569 const loc = std.zig.findLineColumn(source.bytes, start);
3570 try bundle.addRootErrorMessage(.{
3571 .msg = switch (failed.kind) {
3572 .file_outside_module_root => try bundle.addString("import of file outside module path"),
3573 .illegal_zig_import => try bundle.addString("this compiler implementation does not allow importing files from this directory"),
3574 },
3575 .src_loc = try bundle.addSourceLocation(.{
3576 .src_path = try bundle.printString("{}", .{file.path.fmt(comp)}),
3577 .span_start = start,
3578 .span_main = start,
3579 .span_end = @intCast(end),
3580 .line = @intCast(loc.line),
3581 .column = @intCast(loc.column),
3582 .source_line = try bundle.addString(loc.source_line),
3583 }),
3584 .notes_len = 0,
3585 });
3586 }
3587
3588 // Before iterating `failed_files`, we need to sort it into a consistent order so that error
3589 // messages appear consistently despite different ordering from the AstGen worker pool. File
3590 // paths are a great key for this sort! We are using sorting the `ArrayHashMap` itself to
3591 // make sure it reindexes; that's important because these entries need to be retained for
3592 // future updates.
3593 const FileSortCtx = struct {
3594 zcu: *Zcu,
3595 failed_files_keys: []const Zcu.File.Index,
3596 pub fn lessThan(ctx: @This(), lhs_index: usize, rhs_index: usize) bool {
3597 const lhs_path = ctx.zcu.fileByIndex(ctx.failed_files_keys[lhs_index]).path;
3598 const rhs_path = ctx.zcu.fileByIndex(ctx.failed_files_keys[rhs_index]).path;
3599 if (lhs_path.root != rhs_path.root) return @intFromEnum(lhs_path.root) < @intFromEnum(rhs_path.root);
3600 return std.mem.order(u8, lhs_path.sub_path, rhs_path.sub_path).compare(.lt);
3601 }
3602 };
3603 zcu.failed_files.sort(@as(FileSortCtx, .{
3604 .zcu = zcu,
3605 .failed_files_keys = zcu.failed_files.keys(),
3606 }));
3607
3608 for (zcu.failed_files.keys(), zcu.failed_files.values()) |file_index, error_msg| {
3609 if (!zcu.alive_files.contains(file_index)) continue;
3610 const file = zcu.fileByIndex(file_index);
3611 const is_retryable = switch (file.status) {
3612 .retryable_failure => true,
3613 .success, .astgen_failure => false,
3614 .never_loaded => unreachable,
3615 };
3330 if (error_msg) |msg| {3616 if (error_msg) |msg| {
3331 try addModuleErrorMsg(zcu, &bundle, msg.*, false);3617 assert(is_retryable);
3618 try addWholeFileError(zcu, &bundle, file_index, msg);
3332 } else {3619 } else {
3333 // Must be ZIR or Zoir errors. Note that this may include AST errors.3620 assert(!is_retryable);
3334 _ = try file.getTree(gpa); // Tree must be loaded.3621 // AstGen/ZoirGen succeeded with errors. Note that this may include AST errors.
3622 _ = try file.getTree(zcu); // Tree must be loaded.
3623 const path = try std.fmt.allocPrint(gpa, "{}", .{file.path.fmt(comp)});
3624 defer gpa.free(path);
3335 if (file.zir != null) {3625 if (file.zir != null) {
3336 try addZirErrorMessages(&bundle, file);3626 try bundle.addZirErrorMessages(file.zir.?, file.tree.?, file.source.?, path);
3337 } else if (file.zoir != null) {3627 } else if (file.zoir != null) {
3338 try addZoirErrorMessages(&bundle, file);3628 try bundle.addZoirErrorMessages(file.zoir.?, file.tree.?, file.source.?, path);
3339 } else {3629 } else {
3340 // Either Zir or Zoir must have been loaded.3630 // Either Zir or Zoir must have been loaded.
3341 unreachable;3631 unreachable;
...@@ -3646,20 +3936,16 @@ pub fn addModuleErrorMsg(...@@ -3646,20 +3936,16 @@ pub fn addModuleErrorMsg(
3646 const gpa = eb.gpa;3936 const gpa = eb.gpa;
3647 const ip = &zcu.intern_pool;3937 const ip = &zcu.intern_pool;
3648 const err_src_loc = module_err_msg.src_loc.upgrade(zcu);3938 const err_src_loc = module_err_msg.src_loc.upgrade(zcu);
3649 const err_source = err_src_loc.file_scope.getSource(gpa) catch |err| {3939 const err_source = err_src_loc.file_scope.getSource(zcu) catch |err| {
3650 const file_path = try err_src_loc.file_scope.fullPath(gpa);
3651 defer gpa.free(file_path);
3652 try eb.addRootErrorMessage(.{3940 try eb.addRootErrorMessage(.{
3653 .msg = try eb.printString("unable to load '{s}': {s}", .{3941 .msg = try eb.printString("unable to load '{}': {s}", .{
3654 file_path, @errorName(err),3942 err_src_loc.file_scope.path.fmt(zcu.comp), @errorName(err),
3655 }),3943 }),
3656 });3944 });
3657 return;3945 return;
3658 };3946 };
3659 const err_span = try err_src_loc.span(gpa);3947 const err_span = try err_src_loc.span(zcu);
3660 const err_loc = std.zig.findLineColumn(err_source.bytes, err_span.main);3948 const err_loc = std.zig.findLineColumn(err_source.bytes, err_span.main);
3661 const file_path = try err_src_loc.file_scope.fullPath(gpa);
3662 defer gpa.free(file_path);
36633949
3664 var ref_traces: std.ArrayListUnmanaged(ErrorBundle.ReferenceTrace) = .empty;3950 var ref_traces: std.ArrayListUnmanaged(ErrorBundle.ReferenceTrace) = .empty;
3665 defer ref_traces.deinit(gpa);3951 defer ref_traces.deinit(gpa);
...@@ -3715,16 +4001,13 @@ pub fn addModuleErrorMsg(...@@ -3715,16 +4001,13 @@ pub fn addModuleErrorMsg(
3715 }4001 }
37164002
3717 const src_loc = try eb.addSourceLocation(.{4003 const src_loc = try eb.addSourceLocation(.{
3718 .src_path = try eb.addString(file_path),4004 .src_path = try eb.printString("{}", .{err_src_loc.file_scope.path.fmt(zcu.comp)}),
3719 .span_start = err_span.start,4005 .span_start = err_span.start,
3720 .span_main = err_span.main,4006 .span_main = err_span.main,
3721 .span_end = err_span.end,4007 .span_end = err_span.end,
3722 .line = @intCast(err_loc.line),4008 .line = @intCast(err_loc.line),
3723 .column = @intCast(err_loc.column),4009 .column = @intCast(err_loc.column),
3724 .source_line = if (err_src_loc.lazy == .entire_file)4010 .source_line = try eb.addString(err_loc.source_line),
3725 0
3726 else
3727 try eb.addString(err_loc.source_line),
3728 .reference_trace_len = @intCast(ref_traces.items.len),4011 .reference_trace_len = @intCast(ref_traces.items.len),
3729 });4012 });
37304013
...@@ -3740,11 +4023,9 @@ pub fn addModuleErrorMsg(...@@ -3740,11 +4023,9 @@ pub fn addModuleErrorMsg(
3740 var last_note_loc: ?std.zig.Loc = null;4023 var last_note_loc: ?std.zig.Loc = null;
3741 for (module_err_msg.notes) |module_note| {4024 for (module_err_msg.notes) |module_note| {
3742 const note_src_loc = module_note.src_loc.upgrade(zcu);4025 const note_src_loc = module_note.src_loc.upgrade(zcu);
3743 const source = try note_src_loc.file_scope.getSource(gpa);4026 const source = try note_src_loc.file_scope.getSource(zcu);
3744 const span = try note_src_loc.span(gpa);4027 const span = try note_src_loc.span(zcu);
3745 const loc = std.zig.findLineColumn(source.bytes, span.main);4028 const loc = std.zig.findLineColumn(source.bytes, span.main);
3746 const note_file_path = try note_src_loc.file_scope.fullPath(gpa);
3747 defer gpa.free(note_file_path);
37484029
3749 const omit_source_line = loc.eql(err_loc) or (last_note_loc != null and loc.eql(last_note_loc.?));4030 const omit_source_line = loc.eql(err_loc) or (last_note_loc != null and loc.eql(last_note_loc.?));
3750 last_note_loc = loc;4031 last_note_loc = loc;
...@@ -3752,7 +4033,7 @@ pub fn addModuleErrorMsg(...@@ -3752,7 +4033,7 @@ pub fn addModuleErrorMsg(
3752 const gop = try notes.getOrPutContext(gpa, .{4033 const gop = try notes.getOrPutContext(gpa, .{
3753 .msg = try eb.addString(module_note.msg),4034 .msg = try eb.addString(module_note.msg),
3754 .src_loc = try eb.addSourceLocation(.{4035 .src_loc = try eb.addSourceLocation(.{
3755 .src_path = try eb.addString(note_file_path),4036 .src_path = try eb.printString("{}", .{note_src_loc.file_scope.path.fmt(zcu.comp)}),
3756 .span_start = span.start,4037 .span_start = span.start,
3757 .span_main = span.main,4038 .span_main = span.main,
3758 .span_end = span.end,4039 .span_end = span.end,
...@@ -3791,15 +4072,13 @@ fn addReferenceTraceFrame(...@@ -3791,15 +4072,13 @@ fn addReferenceTraceFrame(
3791) !void {4072) !void {
3792 const gpa = zcu.gpa;4073 const gpa = zcu.gpa;
3793 const src = lazy_src.upgrade(zcu);4074 const src = lazy_src.upgrade(zcu);
3794 const source = try src.file_scope.getSource(gpa);4075 const source = try src.file_scope.getSource(zcu);
3795 const span = try src.span(gpa);4076 const span = try src.span(zcu);
3796 const loc = std.zig.findLineColumn(source.bytes, span.main);4077 const loc = std.zig.findLineColumn(source.bytes, span.main);
3797 const rt_file_path = try src.file_scope.fullPath(gpa);
3798 defer gpa.free(rt_file_path);
3799 try ref_traces.append(gpa, .{4078 try ref_traces.append(gpa, .{
3800 .decl_name = try eb.printString("{s}{s}", .{ name, if (inlined) " [inlined]" else "" }),4079 .decl_name = try eb.printString("{s}{s}", .{ name, if (inlined) " [inlined]" else "" }),
3801 .src_loc = try eb.addSourceLocation(.{4080 .src_loc = try eb.addSourceLocation(.{
3802 .src_path = try eb.addString(rt_file_path),4081 .src_path = try eb.printString("{}", .{src.file_scope.path.fmt(zcu.comp)}),
3803 .span_start = span.start,4082 .span_start = span.start,
3804 .span_main = span.main,4083 .span_main = span.main,
3805 .span_end = span.end,4084 .span_end = span.end,
...@@ -3810,18 +4089,30 @@ fn addReferenceTraceFrame(...@@ -3810,18 +4089,30 @@ fn addReferenceTraceFrame(
3810 });4089 });
3811}4090}
38124091
3813pub fn addZirErrorMessages(eb: *ErrorBundle.Wip, file: *Zcu.File) !void {4092pub fn addWholeFileError(
3814 const gpa = eb.gpa;4093 zcu: *Zcu,
3815 const src_path = try file.fullPath(gpa);4094 eb: *ErrorBundle.Wip,
3816 defer gpa.free(src_path);4095 file_index: Zcu.File.Index,
3817 return eb.addZirErrorMessages(file.zir.?, file.tree.?, file.source.?, src_path);4096 msg: []const u8,
3818}4097) !void {
4098 // note: "file imported here" on the import reference token
4099 const imported_note: ?ErrorBundle.MessageIndex = switch (zcu.alive_files.get(file_index).?) {
4100 .analysis_root => null,
4101 .import => |import| try eb.addErrorMessage(.{
4102 .msg = try eb.addString("file imported here"),
4103 .src_loc = try zcu.fileByIndex(import.importer).errorBundleTokenSrc(import.tok, zcu, eb),
4104 }),
4105 };
38194106
3820pub fn addZoirErrorMessages(eb: *ErrorBundle.Wip, file: *Zcu.File) !void {4107 try eb.addRootErrorMessage(.{
3821 const gpa = eb.gpa;4108 .msg = try eb.addString(msg),
3822 const src_path = try file.fullPath(gpa);4109 .src_loc = try zcu.fileByIndex(file_index).errorBundleWholeFileSrc(zcu, eb),
3823 defer gpa.free(src_path);4110 .notes_len = if (imported_note != null) 1 else 0,
3824 return eb.addZoirErrorMessages(file.zoir.?, file.tree.?, file.source.?, src_path);4111 });
4112 if (imported_note) |n| {
4113 const note_idx = try eb.reserveNotes(1);
4114 eb.extra.items[note_idx] = @intFromEnum(n);
4115 }
3825}4116}
38264117
3827pub fn performAllTheWork(4118pub fn performAllTheWork(
...@@ -3966,51 +4257,48 @@ fn performAllTheWorkInner(...@@ -3966,51 +4257,48 @@ fn performAllTheWorkInner(
3966 var astgen_wait_group: WaitGroup = .{};4257 var astgen_wait_group: WaitGroup = .{};
3967 defer astgen_wait_group.wait();4258 defer astgen_wait_group.wait();
39684259
3969 // builtin.zig is handled specially for two reasons:4260 if (comp.zcu) |zcu| {
3970 // 1. to avoid race condition of zig processes truncating each other's builtin.zig files4261 const gpa = zcu.gpa;
3971 // 2. optimization; in the hot path it only incurs a stat() syscall, which happens4262
3972 // in the `astgen_wait_group`.4263 // We cannot reference `zcu.import_table` after we spawn any `workerUpdateFile` jobs,
3973 if (comp.queued_jobs.update_builtin_zig) b: {4264 // because on single-threaded targets the worker will be run eagerly, meaning the
3974 comp.queued_jobs.update_builtin_zig = false;4265 // `import_table` could be mutated, and not even holding `comp.mutex` will save us. So,
3975 if (comp.zcu == null) break :b;4266 // build up a list of the files to update *before* we spawn any jobs.
3976 // TODO put all the modules in a flat array to make them easy to iterate.4267 var astgen_work_items: std.MultiArrayList(struct {
3977 var seen: std.AutoArrayHashMapUnmanaged(*Package.Module, void) = .empty;4268 file_index: Zcu.File.Index,
3978 defer seen.deinit(comp.gpa);4269 file: *Zcu.File,
3979 try seen.put(comp.gpa, comp.root_mod, {});4270 }) = .empty;
3980 var i: usize = 0;4271 defer astgen_work_items.deinit(gpa);
3981 while (i < seen.count()) : (i += 1) {4272 // Not every item in `import_table` will need updating, because some are builtin.zig
3982 const mod = seen.keys()[i];4273 // files. However, most will, so let's just reserve sufficient capacity upfront.
3983 for (mod.deps.values()) |dep|4274 try astgen_work_items.ensureTotalCapacity(gpa, zcu.import_table.count());
3984 try seen.put(comp.gpa, dep, {});4275 for (zcu.import_table.keys()) |file_index| {
39854276 const file = zcu.fileByIndex(file_index);
3986 const file = mod.builtin_file orelse continue;4277 if (file.is_builtin) {
39874278 // This is a `builtin.zig`, so updating is redundant. However, we want to make
3988 comp.thread_pool.spawnWg(&astgen_wait_group, workerUpdateBuiltinZigFile, .{4279 // sure the file contents are still correct on disk, since it can improve the
3989 comp, mod, file,4280 // debugging experience better. That job only needs `file`, so we can kick it
4281 // off right now.
4282 comp.thread_pool.spawnWg(&astgen_wait_group, workerUpdateBuiltinFile, .{ comp, file });
4283 continue;
4284 }
4285 astgen_work_items.appendAssumeCapacity(.{
4286 .file_index = file_index,
4287 .file = file,
3990 });4288 });
3991 }4289 }
3992 }
39934290
3994 if (comp.zcu) |zcu| {4291 // Now that we're not going to touch `zcu.import_table` again, we can spawn `workerUpdateFile` jobs.
3995 {4292 for (astgen_work_items.items(.file_index), astgen_work_items.items(.file)) |file_index, file| {
3996 // Worker threads may append to zcu.files and zcu.import_table4293 comp.thread_pool.spawnWgId(&astgen_wait_group, workerUpdateFile, .{
3997 // so we must hold the lock while spawning those tasks, since4294 comp, file, file_index, zir_prog_node, &astgen_wait_group,
3998 // we access those tables in this loop.4295 });
3999 comp.mutex.lock();
4000 defer comp.mutex.unlock();
4001
4002 while (comp.astgen_work_queue.readItem()) |file_index| {
4003 // Pre-load these things from our single-threaded context since they
4004 // will be needed by the worker threads.
4005 const path_digest = zcu.filePathDigest(file_index);
4006 const file = zcu.fileByIndex(file_index);
4007 comp.thread_pool.spawnWgId(&astgen_wait_group, workerUpdateFile, .{
4008 comp, file, file_index, path_digest, zir_prog_node, &astgen_wait_group, .root,
4009 });
4010 }
4011 }4296 }
40124297
4013 for (0.., zcu.embed_table.values()) |ef_index_usize, ef| {4298 // On the other hand, it's fine to directly iterate `zcu.embed_table.keys()` here
4299 // because `workerUpdateEmbedFile` can't invalidate it. The different here is that one
4300 // `@embedFile` can't trigger analysis of a new `@embedFile`!
4301 for (0.., zcu.embed_table.keys()) |ef_index_usize, ef| {
4014 const ef_index: Zcu.EmbedFile.Index = @enumFromInt(ef_index_usize);4302 const ef_index: Zcu.EmbedFile.Index = @enumFromInt(ef_index_usize);
4015 comp.thread_pool.spawnWgId(&astgen_wait_group, workerUpdateEmbedFile, .{4303 comp.thread_pool.spawnWgId(&astgen_wait_group, workerUpdateEmbedFile, .{
4016 comp, ef_index, ef,4304 comp, ef_index, ef,
...@@ -4035,25 +4323,39 @@ fn performAllTheWorkInner(...@@ -4035,25 +4323,39 @@ fn performAllTheWorkInner(
4035 const pt: Zcu.PerThread = .activate(zcu, .main);4323 const pt: Zcu.PerThread = .activate(zcu, .main);
4036 defer pt.deactivate();4324 defer pt.deactivate();
40374325
4038 // If the cache mode is `whole`, then add every source file to the cache manifest.4326 const gpa = zcu.gpa;
4327
4328 // On an incremental update, a source file might become "dead", in that all imports of
4329 // the file were removed. This could even change what module the file belongs to! As such,
4330 // we do a traversal over the files, to figure out which ones are alive and the modules
4331 // they belong to.
4332 const any_fatal_files = try pt.computeAliveFiles();
4333
4334 // If the cache mode is `whole`, add every alive source file to the manifest.
4039 switch (comp.cache_use) {4335 switch (comp.cache_use) {
4040 .whole => |whole| if (whole.cache_manifest) |man| {4336 .whole => |whole| if (whole.cache_manifest) |man| {
4041 const gpa = zcu.gpa;4337 for (zcu.alive_files.keys()) |file_index| {
4042 for (zcu.import_table.values()) |file_index| {
4043 const file = zcu.fileByIndex(file_index);4338 const file = zcu.fileByIndex(file_index);
4044 const source = file.getSource(gpa) catch |err| {4339
4045 try pt.reportRetryableFileError(file_index, "unable to load source: {s}", .{@errorName(err)});4340 switch (file.status) {
4046 continue;4341 .never_loaded => unreachable, // AstGen tried to load it
4342 .retryable_failure => continue, // the file cannot be read; this is a guaranteed error
4343 .astgen_failure, .success => {}, // the file was read successfully
4344 }
4345
4346 const path = try file.path.toAbsolute(comp.dirs, gpa);
4347 defer gpa.free(path);
4348
4349 const result = res: {
4350 whole.cache_manifest_mutex.lock();
4351 defer whole.cache_manifest_mutex.unlock();
4352 if (file.source) |source| {
4353 break :res man.addFilePostContents(path, source, file.stat);
4354 } else {
4355 break :res man.addFilePost(path);
4356 }
4047 };4357 };
4048 const resolved_path = try std.fs.path.resolve(gpa, &.{4358 result catch |err| switch (err) {
4049 file.mod.root.root_dir.path orelse ".",
4050 file.mod.root.sub_path,
4051 file.sub_file_path,
4052 });
4053 errdefer gpa.free(resolved_path);
4054 whole.cache_manifest_mutex.lock();
4055 defer whole.cache_manifest_mutex.unlock();
4056 man.addFilePostContents(resolved_path, source.bytes, source.stat) catch |err| switch (err) {
4057 error.OutOfMemory => |e| return e,4359 error.OutOfMemory => |e| return e,
4058 else => {4360 else => {
4059 try pt.reportRetryableFileError(file_index, "unable to update cache: {s}", .{@errorName(err)});4361 try pt.reportRetryableFileError(file_index, "unable to update cache: {s}", .{@errorName(err)});
...@@ -4065,23 +4367,14 @@ fn performAllTheWorkInner(...@@ -4065,23 +4367,14 @@ fn performAllTheWorkInner(
4065 .incremental => {},4367 .incremental => {},
4066 }4368 }
40674369
4068 try reportMultiModuleErrors(pt);4370 if (any_fatal_files or
40694371 zcu.multi_module_err != null or
4070 const any_fatal_files = for (zcu.import_table.values()) |file_index| {4372 zcu.failed_imports.items.len > 0 or
4071 const file = zcu.fileByIndex(file_index);4373 comp.alloc_failure_occurred)
4072 switch (file.status) {4374 {
4073 .never_loaded => unreachable, // everything is loaded by the workers
4074 .retryable_failure, .astgen_failure => break true,
4075 .success => {},
4076 }
4077 } else false;
4078
4079 if (any_fatal_files or comp.alloc_failure_occurred) {
4080 // We give up right now! No updating of ZIR refs, no nothing. The idea is that this prevents4375 // We give up right now! No updating of ZIR refs, no nothing. The idea is that this prevents
4081 // us from invalidating lots of incremental dependencies due to files with e.g. parse errors.4376 // us from invalidating lots of incremental dependencies due to files with e.g. parse errors.
4082 // However, this means our analysis data is invalid, so we want to omit all analysis errors.4377 // However, this means our analysis data is invalid, so we want to omit all analysis errors.
4083
4084 assert(zcu.failed_files.count() > 0); // we will get an error
4085 zcu.skip_analysis_this_update = true;4378 zcu.skip_analysis_this_update = true;
4086 return;4379 return;
4087 }4380 }
...@@ -4093,6 +4386,11 @@ fn performAllTheWorkInner(...@@ -4093,6 +4386,11 @@ fn performAllTheWorkInner(
4093 }4386 }
4094 try zcu.flushRetryableFailures();4387 try zcu.flushRetryableFailures();
40954388
4389 // It's analysis time! Queue up our initial analysis.
4390 for (zcu.analysis_roots.slice()) |mod| {
4391 try comp.queueJob(.{ .analyze_mod = mod });
4392 }
4393
4096 zcu.sema_prog_node = main_progress_node.start("Semantic Analysis", 0);4394 zcu.sema_prog_node = main_progress_node.start("Semantic Analysis", 0);
4097 zcu.codegen_prog_node = if (comp.bin_file != null) main_progress_node.start("Code Generation", 0) else .none;4395 zcu.codegen_prog_node = if (comp.bin_file != null) main_progress_node.start("Code Generation", 0) else .none;
4098 }4396 }
...@@ -4236,7 +4534,7 @@ fn processOneJob(tid: usize, comp: *Compilation, job: Job) JobError!void {...@@ -4236,7 +4534,7 @@ fn processOneJob(tid: usize, comp: *Compilation, job: Job) JobError!void {
42364534
4237 const pt: Zcu.PerThread = .activate(comp.zcu.?, @enumFromInt(tid));4535 const pt: Zcu.PerThread = .activate(comp.zcu.?, @enumFromInt(tid));
4238 defer pt.deactivate();4536 defer pt.deactivate();
4239 pt.semaPkg(mod) catch |err| switch (err) {4537 pt.semaMod(mod) catch |err| switch (err) {
4240 error.OutOfMemory => return error.OutOfMemory,4538 error.OutOfMemory => return error.OutOfMemory,
4241 error.AnalysisFail => return,4539 error.AnalysisFail => return,
4242 };4540 };
...@@ -4301,7 +4599,7 @@ fn docsCopyFallible(comp: *Compilation) anyerror!void {...@@ -4301,7 +4599,7 @@ fn docsCopyFallible(comp: *Compilation) anyerror!void {
43014599
4302 for (&[_][]const u8{ "docs/main.js", "docs/index.html" }) |sub_path| {4600 for (&[_][]const u8{ "docs/main.js", "docs/index.html" }) |sub_path| {
4303 const basename = std.fs.path.basename(sub_path);4601 const basename = std.fs.path.basename(sub_path);
4304 comp.zig_lib_directory.handle.copyFile(sub_path, out_dir, basename, .{}) catch |err| {4602 comp.dirs.zig_lib.handle.copyFile(sub_path, out_dir, basename, .{}) catch |err| {
4305 comp.lockAndSetMiscFailure(.docs_copy, "unable to copy {s}: {s}", .{4603 comp.lockAndSetMiscFailure(.docs_copy, "unable to copy {s}: {s}", .{
4306 sub_path,4604 sub_path,
4307 @errorName(err),4605 @errorName(err),
...@@ -4338,10 +4636,12 @@ fn docsCopyFallible(comp: *Compilation) anyerror!void {...@@ -4338,10 +4636,12 @@ fn docsCopyFallible(comp: *Compilation) anyerror!void {
43384636
4339fn docsCopyModule(comp: *Compilation, module: *Package.Module, name: []const u8, tar_file: std.fs.File) !void {4637fn docsCopyModule(comp: *Compilation, module: *Package.Module, name: []const u8, tar_file: std.fs.File) !void {
4340 const root = module.root;4638 const root = module.root;
4341 const sub_path = if (root.sub_path.len == 0) "." else root.sub_path;4639 var mod_dir = d: {
4342 var mod_dir = root.root_dir.handle.openDir(sub_path, .{ .iterate = true }) catch |err| {4640 const root_dir, const sub_path = root.openInfo(comp.dirs);
4641 break :d root_dir.openDir(sub_path, .{ .iterate = true });
4642 } catch |err| {
4343 return comp.lockAndSetMiscFailure(.docs_copy, "unable to open directory '{}': {s}", .{4643 return comp.lockAndSetMiscFailure(.docs_copy, "unable to open directory '{}': {s}", .{
4344 root, @errorName(err),4644 root.fmt(comp), @errorName(err),
4345 });4645 });
4346 };4646 };
4347 defer mod_dir.close();4647 defer mod_dir.close();
...@@ -4363,13 +4663,13 @@ fn docsCopyModule(comp: *Compilation, module: *Package.Module, name: []const u8,...@@ -4363,13 +4663,13 @@ fn docsCopyModule(comp: *Compilation, module: *Package.Module, name: []const u8,
4363 }4663 }
4364 var file = mod_dir.openFile(entry.path, .{}) catch |err| {4664 var file = mod_dir.openFile(entry.path, .{}) catch |err| {
4365 return comp.lockAndSetMiscFailure(.docs_copy, "unable to open '{}{s}': {s}", .{4665 return comp.lockAndSetMiscFailure(.docs_copy, "unable to open '{}{s}': {s}", .{
4366 root, entry.path, @errorName(err),4666 root.fmt(comp), entry.path, @errorName(err),
4367 });4667 });
4368 };4668 };
4369 defer file.close();4669 defer file.close();
4370 archiver.writeFile(entry.path, file) catch |err| {4670 archiver.writeFile(entry.path, file) catch |err| {
4371 return comp.lockAndSetMiscFailure(.docs_copy, "unable to archive '{}{s}': {s}", .{4671 return comp.lockAndSetMiscFailure(.docs_copy, "unable to archive '{}{s}': {s}", .{
4372 root, entry.path, @errorName(err),4672 root.fmt(comp), entry.path, @errorName(err),
4373 });4673 });
4374 };4674 };
4375 }4675 }
...@@ -4430,13 +4730,11 @@ fn workerDocsWasmFallible(comp: *Compilation, prog_node: std.Progress.Node) anye...@@ -4430,13 +4730,11 @@ fn workerDocsWasmFallible(comp: *Compilation, prog_node: std.Progress.Node) anye
4430 const src_basename = "main.zig";4730 const src_basename = "main.zig";
4431 const root_name = std.fs.path.stem(src_basename);4731 const root_name = std.fs.path.stem(src_basename);
44324732
4733 const dirs = comp.dirs.withoutLocalCache();
4734
4433 const root_mod = try Package.Module.create(arena, .{4735 const root_mod = try Package.Module.create(arena, .{
4434 .global_cache_directory = comp.global_cache_directory,
4435 .paths = .{4736 .paths = .{
4436 .root = .{4737 .root = try .fromRoot(arena, dirs, .zig_lib, "docs/wasm"),
4437 .root_dir = comp.zig_lib_directory,
4438 .sub_path = "docs/wasm",
4439 },
4440 .root_src_path = src_basename,4738 .root_src_path = src_basename,
4441 },4739 },
4442 .fully_qualified_name = root_name,4740 .fully_qualified_name = root_name,
...@@ -4447,16 +4745,10 @@ fn workerDocsWasmFallible(comp: *Compilation, prog_node: std.Progress.Node) anye...@@ -4447,16 +4745,10 @@ fn workerDocsWasmFallible(comp: *Compilation, prog_node: std.Progress.Node) anye
4447 .global = config,4745 .global = config,
4448 .cc_argv = &.{},4746 .cc_argv = &.{},
4449 .parent = null,4747 .parent = null,
4450 .builtin_mod = null,
4451 .builtin_modules = null,
4452 });4748 });
4453 const walk_mod = try Package.Module.create(arena, .{4749 const walk_mod = try Package.Module.create(arena, .{
4454 .global_cache_directory = comp.global_cache_directory,
4455 .paths = .{4750 .paths = .{
4456 .root = .{4751 .root = try .fromRoot(arena, dirs, .zig_lib, "docs/wasm"),
4457 .root_dir = comp.zig_lib_directory,
4458 .sub_path = "docs/wasm",
4459 },
4460 .root_src_path = "Walk.zig",4752 .root_src_path = "Walk.zig",
4461 },4753 },
4462 .fully_qualified_name = "Walk",4754 .fully_qualified_name = "Walk",
...@@ -4467,8 +4759,6 @@ fn workerDocsWasmFallible(comp: *Compilation, prog_node: std.Progress.Node) anye...@@ -4467,8 +4759,6 @@ fn workerDocsWasmFallible(comp: *Compilation, prog_node: std.Progress.Node) anye
4467 .global = config,4759 .global = config,
4468 .cc_argv = &.{},4760 .cc_argv = &.{},
4469 .parent = root_mod,4761 .parent = root_mod,
4470 .builtin_mod = root_mod.getBuiltinDependency(),
4471 .builtin_modules = null, // `builtin_mod` is set
4472 });4762 });
4473 try root_mod.deps.put(arena, "Walk", walk_mod);4763 try root_mod.deps.put(arena, "Walk", walk_mod);
4474 const bin_basename = try std.zig.binNameAlloc(arena, .{4764 const bin_basename = try std.zig.binNameAlloc(arena, .{
...@@ -4478,9 +4768,7 @@ fn workerDocsWasmFallible(comp: *Compilation, prog_node: std.Progress.Node) anye...@@ -4478,9 +4768,7 @@ fn workerDocsWasmFallible(comp: *Compilation, prog_node: std.Progress.Node) anye
4478 });4768 });
44794769
4480 const sub_compilation = try Compilation.create(gpa, arena, .{4770 const sub_compilation = try Compilation.create(gpa, arena, .{
4481 .global_cache_directory = comp.global_cache_directory,4771 .dirs = dirs,
4482 .local_cache_directory = comp.global_cache_directory,
4483 .zig_lib_directory = comp.zig_lib_directory,
4484 .self_exe_path = comp.self_exe_path,4772 .self_exe_path = comp.self_exe_path,
4485 .config = config,4773 .config = config,
4486 .root_mod = root_mod,4774 .root_mod = root_mod,
...@@ -4517,14 +4805,14 @@ fn workerDocsWasmFallible(comp: *Compilation, prog_node: std.Progress.Node) anye...@@ -4517,14 +4805,14 @@ fn workerDocsWasmFallible(comp: *Compilation, prog_node: std.Progress.Node) anye
4517 };4805 };
4518 defer out_dir.close();4806 defer out_dir.close();
45194807
4520 sub_compilation.local_cache_directory.handle.copyFile(4808 sub_compilation.dirs.local_cache.handle.copyFile(
4521 sub_compilation.cache_use.whole.bin_sub_path.?,4809 sub_compilation.cache_use.whole.bin_sub_path.?,
4522 out_dir,4810 out_dir,
4523 "main.wasm",4811 "main.wasm",
4524 .{},4812 .{},
4525 ) catch |err| {4813 ) catch |err| {
4526 return comp.lockAndSetMiscFailure(.docs_copy, "unable to copy '{}{s}' to '{}{s}': {s}", .{4814 return comp.lockAndSetMiscFailure(.docs_copy, "unable to copy '{}{s}' to '{}{s}': {s}", .{
4527 sub_compilation.local_cache_directory,4815 sub_compilation.dirs.local_cache,
4528 sub_compilation.cache_use.whole.bin_sub_path.?,4816 sub_compilation.cache_use.whole.bin_sub_path.?,
4529 emit.root_dir,4817 emit.root_dir,
4530 emit.sub_path,4818 emit.sub_path,
...@@ -4538,28 +4826,23 @@ fn workerUpdateFile(...@@ -4538,28 +4826,23 @@ fn workerUpdateFile(
4538 comp: *Compilation,4826 comp: *Compilation,
4539 file: *Zcu.File,4827 file: *Zcu.File,
4540 file_index: Zcu.File.Index,4828 file_index: Zcu.File.Index,
4541 path_digest: Cache.BinDigest,
4542 prog_node: std.Progress.Node,4829 prog_node: std.Progress.Node,
4543 wg: *WaitGroup,4830 wg: *WaitGroup,
4544 src: Zcu.AstGenSrc,
4545) void {4831) void {
4546 const child_prog_node = prog_node.start(file.sub_file_path, 0);4832 const child_prog_node = prog_node.start(std.fs.path.basename(file.path.sub_path), 0);
4547 defer child_prog_node.end();4833 defer child_prog_node.end();
45484834
4549 const pt: Zcu.PerThread = .activate(comp.zcu.?, @enumFromInt(tid));4835 const pt: Zcu.PerThread = .activate(comp.zcu.?, @enumFromInt(tid));
4550 defer pt.deactivate();4836 defer pt.deactivate();
4551 pt.updateFile(file, path_digest) catch |err| switch (err) {4837 pt.updateFile(file_index, file) catch |err| {
4552 error.AnalysisFail => return,4838 pt.reportRetryableFileError(file_index, "unable to load '{s}': {s}", .{ std.fs.path.basename(file.path.sub_path), @errorName(err) }) catch |oom| switch (oom) {
4553 else => {4839 error.OutOfMemory => {
4554 pt.reportRetryableAstGenError(src, file_index, err) catch |oom| switch (oom) {4840 comp.mutex.lock();
4555 error.OutOfMemory => {4841 defer comp.mutex.unlock();
4556 comp.mutex.lock();4842 comp.setAllocFailure();
4557 defer comp.mutex.unlock();4843 },
4558 comp.setAllocFailure();4844 };
4559 },4845 return;
4560 };
4561 return;
4562 },
4563 };4846 };
45644847
4565 switch (file.getMode()) {4848 switch (file.getMode()) {
...@@ -4567,9 +4850,9 @@ fn workerUpdateFile(...@@ -4567,9 +4850,9 @@ fn workerUpdateFile(
4567 .zon => return, // ZON can't import anything so we're done4850 .zon => return, // ZON can't import anything so we're done
4568 }4851 }
45694852
4570 // Pre-emptively look for `@import` paths and queue them up.4853 // Discover all imports in the file. Imports of modules we ignore for now since we don't
4571 // If we experience an error preemptively fetching the4854 // know which module we're in, but imports of file paths might need us to queue up other
4572 // file, just ignore it and let it happen again later during Sema.4855 // AstGen jobs.
4573 const imports_index = file.zir.?.extra[@intFromEnum(Zir.ExtraIndex.imports)];4856 const imports_index = file.zir.?.extra[@intFromEnum(Zir.ExtraIndex.imports)];
4574 if (imports_index != 0) {4857 if (imports_index != 0) {
4575 const extra = file.zir.?.extraData(Zir.Inst.Imports, imports_index);4858 const extra = file.zir.?.extraData(Zir.Inst.Imports, imports_index);
...@@ -4581,54 +4864,34 @@ fn workerUpdateFile(...@@ -4581,54 +4864,34 @@ fn workerUpdateFile(
4581 extra_index = item.end;4864 extra_index = item.end;
45824865
4583 const import_path = file.zir.?.nullTerminatedString(item.data.name);4866 const import_path = file.zir.?.nullTerminatedString(item.data.name);
4584 // `@import("builtin")` is handled specially.
4585 if (mem.eql(u8, import_path, "builtin")) continue;
4586
4587 const import_result, const imported_path_digest = blk: {
4588 comp.mutex.lock();
4589 defer comp.mutex.unlock();
45904867
4591 const res = pt.importFile(file, import_path) catch continue;4868 if (pt.discoverImport(file.path, import_path)) |res| switch (res) {
4592 if (!res.is_pkg) {4869 .module, .existing_file => {},
4593 res.file.addReference(pt.zcu, .{ .import = .{4870 .new_file => |new| {
4594 .file = file_index,4871 comp.thread_pool.spawnWgId(wg, workerUpdateFile, .{
4595 .token = item.data.token,4872 comp, new.file, new.index, prog_node, wg,
4596 } }) catch continue;4873 });
4597 }4874 },
4598 if (res.is_new) if (comp.file_system_inputs) |fsi| {4875 } else |err| switch (err) {
4599 comp.appendFileSystemInput(fsi, res.file.mod.root, res.file.sub_file_path) catch continue;4876 error.OutOfMemory => {
4600 };4877 comp.mutex.lock();
4601 const imported_path_digest = pt.zcu.filePathDigest(res.file_index);4878 defer comp.mutex.unlock();
4602 break :blk .{ res, imported_path_digest };4879 comp.setAllocFailure();
4603 };4880 },
4604 if (import_result.is_new) {
4605 log.debug("AstGen of {s} has import '{s}'; queuing AstGen of {s}", .{
4606 file.sub_file_path, import_path, import_result.file.sub_file_path,
4607 });
4608 const sub_src: Zcu.AstGenSrc = .{ .import = .{
4609 .importing_file = file_index,
4610 .import_tok = item.data.token,
4611 } };
4612 comp.thread_pool.spawnWgId(wg, workerUpdateFile, .{
4613 comp, import_result.file, import_result.file_index, imported_path_digest, prog_node, wg, sub_src,
4614 });
4615 }4881 }
4616 }4882 }
4617 }4883 }
4618}4884}
46194885
4620fn workerUpdateBuiltinZigFile(4886fn workerUpdateBuiltinFile(comp: *Compilation, file: *Zcu.File) void {
4621 comp: *Compilation,4887 Builtin.updateFileOnDisk(file, comp) catch |err| {
4622 mod: *Package.Module,
4623 file: *Zcu.File,
4624) void {
4625 Builtin.populateFile(comp, mod, file) catch |err| {
4626 comp.mutex.lock();4888 comp.mutex.lock();
4627 defer comp.mutex.unlock();4889 defer comp.mutex.unlock();
46284890 comp.setMiscFailure(
4629 comp.setMiscFailure(.write_builtin_zig, "unable to write '{}{s}': {s}", .{4891 .write_builtin_zig,
4630 mod.root, mod.root_src_path, @errorName(err),4892 "unable to write '{}': {s}",
4631 });4893 .{ file.path.fmt(comp), @errorName(err) },
4894 );
4632 };4895 };
4633}4896}
46344897
...@@ -4738,10 +5001,10 @@ pub fn cImport(comp: *Compilation, c_src: []const u8, owner_mod: *Package.Module...@@ -4738,10 +5001,10 @@ pub fn cImport(comp: *Compilation, c_src: []const u8, owner_mod: *Package.Module
47385001
4739 const tmp_digest = man.hash.peek();5002 const tmp_digest = man.hash.peek();
4740 const tmp_dir_sub_path = try std.fs.path.join(arena, &[_][]const u8{ "o", &tmp_digest });5003 const tmp_dir_sub_path = try std.fs.path.join(arena, &[_][]const u8{ "o", &tmp_digest });
4741 var zig_cache_tmp_dir = try comp.local_cache_directory.handle.makeOpenPath(tmp_dir_sub_path, .{});5004 var zig_cache_tmp_dir = try comp.dirs.local_cache.handle.makeOpenPath(tmp_dir_sub_path, .{});
4742 defer zig_cache_tmp_dir.close();5005 defer zig_cache_tmp_dir.close();
4743 const cimport_basename = "cimport.h";5006 const cimport_basename = "cimport.h";
4744 const out_h_path = try comp.local_cache_directory.join(arena, &[_][]const u8{5007 const out_h_path = try comp.dirs.local_cache.join(arena, &[_][]const u8{
4745 tmp_dir_sub_path, cimport_basename,5008 tmp_dir_sub_path, cimport_basename,
4746 });5009 });
4747 const out_dep_path = try std.fmt.allocPrint(arena, "{s}.d", .{out_h_path});5010 const out_dep_path = try std.fmt.allocPrint(arena, "{s}.d", .{out_h_path});
...@@ -4779,7 +5042,7 @@ pub fn cImport(comp: *Compilation, c_src: []const u8, owner_mod: *Package.Module...@@ -4779,7 +5042,7 @@ pub fn cImport(comp: *Compilation, c_src: []const u8, owner_mod: *Package.Module
4779 new_argv[i] = try arena.dupeZ(u8, arg);5042 new_argv[i] = try arena.dupeZ(u8, arg);
4780 }5043 }
47815044
4782 const c_headers_dir_path_z = try comp.zig_lib_directory.joinZ(arena, &[_][]const u8{"include"});5045 const c_headers_dir_path_z = try comp.dirs.zig_lib.joinZ(arena, &.{"include"});
4783 var errors = std.zig.ErrorBundle.empty;5046 var errors = std.zig.ErrorBundle.empty;
4784 errdefer errors.deinit(comp.gpa);5047 errdefer errors.deinit(comp.gpa);
4785 break :tree translate_c.translate(5048 break :tree translate_c.translate(
...@@ -4820,7 +5083,7 @@ pub fn cImport(comp: *Compilation, c_src: []const u8, owner_mod: *Package.Module...@@ -4820,7 +5083,7 @@ pub fn cImport(comp: *Compilation, c_src: []const u8, owner_mod: *Package.Module
4820 const bin_digest = man.finalBin();5083 const bin_digest = man.finalBin();
4821 const hex_digest = Cache.binToHex(bin_digest);5084 const hex_digest = Cache.binToHex(bin_digest);
4822 const o_sub_path = "o" ++ std.fs.path.sep_str ++ hex_digest;5085 const o_sub_path = "o" ++ std.fs.path.sep_str ++ hex_digest;
4823 var o_dir = try comp.local_cache_directory.handle.makeOpenPath(o_sub_path, .{});5086 var o_dir = try comp.dirs.local_cache.handle.makeOpenPath(o_sub_path, .{});
4824 defer o_dir.close();5087 defer o_dir.close();
48255088
4826 var out_zig_file = try o_dir.createFile(cimport_zig_basename, .{});5089 var out_zig_file = try o_dir.createFile(cimport_zig_basename, .{});
...@@ -5226,7 +5489,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr...@@ -5226,7 +5489,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr
5226 // We can't know the digest until we do the C compiler invocation,5489 // We can't know the digest until we do the C compiler invocation,
5227 // so we need a temporary filename.5490 // so we need a temporary filename.
5228 const out_obj_path = try comp.tmpFilePath(arena, o_basename);5491 const out_obj_path = try comp.tmpFilePath(arena, o_basename);
5229 var zig_cache_tmp_dir = try comp.local_cache_directory.handle.makeOpenPath("tmp", .{});5492 var zig_cache_tmp_dir = try comp.dirs.local_cache.handle.makeOpenPath("tmp", .{});
5230 defer zig_cache_tmp_dir.close();5493 defer zig_cache_tmp_dir.close();
52315494
5232 const out_diag_path = if (comp.clang_passthrough_mode or !ext.clangSupportsDiagnostics())5495 const out_diag_path = if (comp.clang_passthrough_mode or !ext.clangSupportsDiagnostics())
...@@ -5362,7 +5625,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr...@@ -5362,7 +5625,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr
5362 // Rename into place.5625 // Rename into place.
5363 const digest = man.final();5626 const digest = man.final();
5364 const o_sub_path = try std.fs.path.join(arena, &[_][]const u8{ "o", &digest });5627 const o_sub_path = try std.fs.path.join(arena, &[_][]const u8{ "o", &digest });
5365 var o_dir = try comp.local_cache_directory.handle.makeOpenPath(o_sub_path, .{});5628 var o_dir = try comp.dirs.local_cache.handle.makeOpenPath(o_sub_path, .{});
5366 defer o_dir.close();5629 defer o_dir.close();
5367 const tmp_basename = std.fs.path.basename(out_obj_path);5630 const tmp_basename = std.fs.path.basename(out_obj_path);
5368 try std.fs.rename(zig_cache_tmp_dir, tmp_basename, o_dir, o_basename);5631 try std.fs.rename(zig_cache_tmp_dir, tmp_basename, o_dir, o_basename);
...@@ -5386,7 +5649,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr...@@ -5386,7 +5649,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr
5386 c_object.status = .{5649 c_object.status = .{
5387 .success = .{5650 .success = .{
5388 .object_path = .{5651 .object_path = .{
5389 .root_dir = comp.local_cache_directory,5652 .root_dir = comp.dirs.local_cache,
5390 .sub_path = try std.fs.path.join(gpa, &.{ "o", &digest, o_basename }),5653 .sub_path = try std.fs.path.join(gpa, &.{ "o", &digest, o_basename }),
5391 },5654 },
5392 .lock = man.toOwnedLock(),5655 .lock = man.toOwnedLock(),
...@@ -5449,13 +5712,13 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32...@@ -5449,13 +5712,13 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32
5449 const digest = man.final();5712 const digest = man.final();
54505713
5451 const o_sub_path = try std.fs.path.join(arena, &.{ "o", &digest });5714 const o_sub_path = try std.fs.path.join(arena, &.{ "o", &digest });
5452 var o_dir = try comp.local_cache_directory.handle.makeOpenPath(o_sub_path, .{});5715 var o_dir = try comp.dirs.local_cache.handle.makeOpenPath(o_sub_path, .{});
5453 defer o_dir.close();5716 defer o_dir.close();
54545717
5455 const in_rc_path = try comp.local_cache_directory.join(comp.gpa, &.{5718 const in_rc_path = try comp.dirs.local_cache.join(comp.gpa, &.{
5456 o_sub_path, rc_basename,5719 o_sub_path, rc_basename,
5457 });5720 });
5458 const out_res_path = try comp.local_cache_directory.join(comp.gpa, &.{5721 const out_res_path = try comp.dirs.local_cache.join(comp.gpa, &.{
5459 o_sub_path, res_basename,5722 o_sub_path, res_basename,
5460 });5723 });
54615724
...@@ -5517,7 +5780,7 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32...@@ -5517,7 +5780,7 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32
55175780
5518 win32_resource.status = .{5781 win32_resource.status = .{
5519 .success = .{5782 .success = .{
5520 .res_path = try comp.local_cache_directory.join(comp.gpa, &[_][]const u8{5783 .res_path = try comp.dirs.local_cache.join(comp.gpa, &[_][]const u8{
5521 "o", &digest, res_basename,5784 "o", &digest, res_basename,
5522 }),5785 }),
5523 .lock = man.toOwnedLock(),5786 .lock = man.toOwnedLock(),
...@@ -5535,7 +5798,7 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32...@@ -5535,7 +5798,7 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32
5535 const rc_basename_noext = src_basename[0 .. src_basename.len - std.fs.path.extension(src_basename).len];5798 const rc_basename_noext = src_basename[0 .. src_basename.len - std.fs.path.extension(src_basename).len];
55365799
5537 const digest = if (try man.hit()) man.final() else blk: {5800 const digest = if (try man.hit()) man.final() else blk: {
5538 var zig_cache_tmp_dir = try comp.local_cache_directory.handle.makeOpenPath("tmp", .{});5801 var zig_cache_tmp_dir = try comp.dirs.local_cache.handle.makeOpenPath("tmp", .{});
5539 defer zig_cache_tmp_dir.close();5802 defer zig_cache_tmp_dir.close();
55405803
5541 const res_filename = try std.fmt.allocPrint(arena, "{s}.res", .{rc_basename_noext});5804 const res_filename = try std.fmt.allocPrint(arena, "{s}.res", .{rc_basename_noext});
...@@ -5605,7 +5868,7 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32...@@ -5605,7 +5868,7 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32
5605 // Rename into place.5868 // Rename into place.
5606 const digest = man.final();5869 const digest = man.final();
5607 const o_sub_path = try std.fs.path.join(arena, &[_][]const u8{ "o", &digest });5870 const o_sub_path = try std.fs.path.join(arena, &[_][]const u8{ "o", &digest });
5608 var o_dir = try comp.local_cache_directory.handle.makeOpenPath(o_sub_path, .{});5871 var o_dir = try comp.dirs.local_cache.handle.makeOpenPath(o_sub_path, .{});
5609 defer o_dir.close();5872 defer o_dir.close();
5610 const tmp_basename = std.fs.path.basename(out_res_path);5873 const tmp_basename = std.fs.path.basename(out_res_path);
5611 try std.fs.rename(zig_cache_tmp_dir, tmp_basename, o_dir, res_filename);5874 try std.fs.rename(zig_cache_tmp_dir, tmp_basename, o_dir, res_filename);
...@@ -5626,7 +5889,7 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32...@@ -5626,7 +5889,7 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32
56265889
5627 win32_resource.status = .{5890 win32_resource.status = .{
5628 .success = .{5891 .success = .{
5629 .res_path = try comp.local_cache_directory.join(comp.gpa, &[_][]const u8{5892 .res_path = try comp.dirs.local_cache.join(comp.gpa, &[_][]const u8{
5630 "o", &digest, res_basename,5893 "o", &digest, res_basename,
5631 }),5894 }),
5632 .lock = man.toOwnedLock(),5895 .lock = man.toOwnedLock(),
...@@ -5721,7 +5984,7 @@ fn spawnZigRc(...@@ -5721,7 +5984,7 @@ fn spawnZigRc(
5721pub fn tmpFilePath(comp: Compilation, ally: Allocator, suffix: []const u8) error{OutOfMemory}![]const u8 {5984pub fn tmpFilePath(comp: Compilation, ally: Allocator, suffix: []const u8) error{OutOfMemory}![]const u8 {
5722 const s = std.fs.path.sep_str;5985 const s = std.fs.path.sep_str;
5723 const rand_int = std.crypto.random.int(u64);5986 const rand_int = std.crypto.random.int(u64);
5724 if (comp.local_cache_directory.path) |p| {5987 if (comp.dirs.local_cache.path) |p| {
5725 return std.fmt.allocPrint(ally, "{s}" ++ s ++ "tmp" ++ s ++ "{x}-{s}", .{ p, rand_int, suffix });5988 return std.fmt.allocPrint(ally, "{s}" ++ s ++ "tmp" ++ s ++ "{x}-{s}", .{ p, rand_int, suffix });
5726 } else {5989 } else {
5727 return std.fmt.allocPrint(ally, "tmp" ++ s ++ "{x}-{s}", .{ rand_int, suffix });5990 return std.fmt.allocPrint(ally, "tmp" ++ s ++ "{x}-{s}", .{ rand_int, suffix });
...@@ -5962,12 +6225,12 @@ pub fn addCCArgs(...@@ -5962,12 +6225,12 @@ pub fn addCCArgs(
5962 if (comp.config.link_libcpp) {6225 if (comp.config.link_libcpp) {
5963 try argv.append("-isystem");6226 try argv.append("-isystem");
5964 try argv.append(try std.fs.path.join(arena, &[_][]const u8{6227 try argv.append(try std.fs.path.join(arena, &[_][]const u8{
5965 comp.zig_lib_directory.path.?, "libcxx", "include",6228 comp.dirs.zig_lib.path.?, "libcxx", "include",
5966 }));6229 }));
59676230
5968 try argv.append("-isystem");6231 try argv.append("-isystem");
5969 try argv.append(try std.fs.path.join(arena, &[_][]const u8{6232 try argv.append(try std.fs.path.join(arena, &[_][]const u8{
5970 comp.zig_lib_directory.path.?, "libcxxabi", "include",6233 comp.dirs.zig_lib.path.?, "libcxxabi", "include",
5971 }));6234 }));
59726235
5973 try libcxx.addCxxArgs(comp, arena, argv);6236 try libcxx.addCxxArgs(comp, arena, argv);
...@@ -5977,7 +6240,7 @@ pub fn addCCArgs(...@@ -5977,7 +6240,7 @@ pub fn addCCArgs(
5977 // However as noted by @dimenus, appending libc headers before compiler headers breaks6240 // However as noted by @dimenus, appending libc headers before compiler headers breaks
5978 // intrinsics and other compiler specific items.6241 // intrinsics and other compiler specific items.
5979 try argv.append("-isystem");6242 try argv.append("-isystem");
5980 try argv.append(try std.fs.path.join(arena, &[_][]const u8{ comp.zig_lib_directory.path.?, "include" }));6243 try argv.append(try std.fs.path.join(arena, &.{ comp.dirs.zig_lib.path.?, "include" }));
59816244
5982 try argv.ensureUnusedCapacity(comp.libc_include_dir_list.len * 2);6245 try argv.ensureUnusedCapacity(comp.libc_include_dir_list.len * 2);
5983 for (comp.libc_include_dir_list) |include_dir| {6246 for (comp.libc_include_dir_list) |include_dir| {
...@@ -5996,7 +6259,7 @@ pub fn addCCArgs(...@@ -5996,7 +6259,7 @@ pub fn addCCArgs(
5996 if (comp.config.link_libunwind) {6259 if (comp.config.link_libunwind) {
5997 try argv.append("-isystem");6260 try argv.append("-isystem");
5998 try argv.append(try std.fs.path.join(arena, &[_][]const u8{6261 try argv.append(try std.fs.path.join(arena, &[_][]const u8{
5999 comp.zig_lib_directory.path.?, "libunwind", "include",6262 comp.dirs.zig_lib.path.?, "libunwind", "include",
6000 }));6263 }));
6001 }6264 }
60026265
...@@ -6584,12 +6847,12 @@ test "classifyFileExt" {...@@ -6584,12 +6847,12 @@ test "classifyFileExt" {
6584 try std.testing.expectEqual(FileExt.zig, classifyFileExt("foo.zig"));6847 try std.testing.expectEqual(FileExt.zig, classifyFileExt("foo.zig"));
6585}6848}
65866849
6587fn get_libc_crt_file(comp: *Compilation, arena: Allocator, basename: []const u8) !Path {6850fn get_libc_crt_file(comp: *Compilation, arena: Allocator, basename: []const u8) !Cache.Path {
6588 return (try crtFilePath(&comp.crt_files, basename)) orelse {6851 return (try crtFilePath(&comp.crt_files, basename)) orelse {
6589 const lci = comp.libc_installation orelse return error.LibCInstallationNotAvailable;6852 const lci = comp.libc_installation orelse return error.LibCInstallationNotAvailable;
6590 const crt_dir_path = lci.crt_dir orelse return error.LibCInstallationMissingCrtDir;6853 const crt_dir_path = lci.crt_dir orelse return error.LibCInstallationMissingCrtDir;
6591 const full_path = try std.fs.path.join(arena, &[_][]const u8{ crt_dir_path, basename });6854 const full_path = try std.fs.path.join(arena, &[_][]const u8{ crt_dir_path, basename });
6592 return Path.initCwd(full_path);6855 return Cache.Path.initCwd(full_path);
6593 };6856 };
6594}6857}
65956858
...@@ -6598,7 +6861,7 @@ pub fn crtFileAsString(comp: *Compilation, arena: Allocator, basename: []const u...@@ -6598,7 +6861,7 @@ pub fn crtFileAsString(comp: *Compilation, arena: Allocator, basename: []const u
6598 return path.toString(arena);6861 return path.toString(arena);
6599}6862}
66006863
6601fn crtFilePath(crt_files: *std.StringHashMapUnmanaged(CrtFile), basename: []const u8) Allocator.Error!?Path {6864fn crtFilePath(crt_files: *std.StringHashMapUnmanaged(CrtFile), basename: []const u8) Allocator.Error!?Cache.Path {
6602 const crt_file = crt_files.get(basename) orelse return null;6865 const crt_file = crt_files.get(basename) orelse return null;
6603 return crt_file.full_object_path;6866 return crt_file.full_object_path;
6604}6867}
...@@ -6736,9 +6999,8 @@ fn buildOutputFromZig(...@@ -6736,9 +6999,8 @@ fn buildOutputFromZig(
6736 });6999 });
67377000
6738 const root_mod = try Package.Module.create(arena, .{7001 const root_mod = try Package.Module.create(arena, .{
6739 .global_cache_directory = comp.global_cache_directory,
6740 .paths = .{7002 .paths = .{
6741 .root = .{ .root_dir = comp.zig_lib_directory },7003 .root = .zig_lib_root,
6742 .root_src_path = src_basename,7004 .root_src_path = src_basename,
6743 },7005 },
6744 .fully_qualified_name = "root",7006 .fully_qualified_name = "root",
...@@ -6760,8 +7022,6 @@ fn buildOutputFromZig(...@@ -6760,8 +7022,6 @@ fn buildOutputFromZig(
6760 .global = config,7022 .global = config,
6761 .cc_argv = &.{},7023 .cc_argv = &.{},
6762 .parent = null,7024 .parent = null,
6763 .builtin_mod = null,
6764 .builtin_modules = null, // there is only one module in this compilation
6765 });7025 });
6766 const target = comp.getTarget();7026 const target = comp.getTarget();
6767 const bin_basename = try std.zig.binNameAlloc(arena, .{7027 const bin_basename = try std.zig.binNameAlloc(arena, .{
...@@ -6785,9 +7045,7 @@ fn buildOutputFromZig(...@@ -6785,9 +7045,7 @@ fn buildOutputFromZig(
6785 };7045 };
67867046
6787 const sub_compilation = try Compilation.create(gpa, arena, .{7047 const sub_compilation = try Compilation.create(gpa, arena, .{
6788 .global_cache_directory = comp.global_cache_directory,7048 .dirs = comp.dirs.withoutLocalCache(),
6789 .local_cache_directory = comp.global_cache_directory,
6790 .zig_lib_directory = comp.zig_lib_directory,
6791 .cache_mode = .whole,7049 .cache_mode = .whole,
6792 .parent_whole_cache = parent_whole_cache,7050 .parent_whole_cache = parent_whole_cache,
6793 .self_exe_path = comp.self_exe_path,7051 .self_exe_path = comp.self_exe_path,
...@@ -6878,9 +7136,8 @@ pub fn build_crt_file(...@@ -6878,9 +7136,8 @@ pub fn build_crt_file(
6878 },7136 },
6879 });7137 });
6880 const root_mod = try Package.Module.create(arena, .{7138 const root_mod = try Package.Module.create(arena, .{
6881 .global_cache_directory = comp.global_cache_directory,
6882 .paths = .{7139 .paths = .{
6883 .root = .{ .root_dir = comp.zig_lib_directory },7140 .root = .zig_lib_root,
6884 .root_src_path = "",7141 .root_src_path = "",
6885 },7142 },
6886 .fully_qualified_name = "root",7143 .fully_qualified_name = "root",
...@@ -6908,8 +7165,6 @@ pub fn build_crt_file(...@@ -6908,8 +7165,6 @@ pub fn build_crt_file(
6908 .global = config,7165 .global = config,
6909 .cc_argv = &.{},7166 .cc_argv = &.{},
6910 .parent = null,7167 .parent = null,
6911 .builtin_mod = null,
6912 .builtin_modules = null, // there is only one module in this compilation
6913 });7168 });
69147169
6915 for (c_source_files) |*item| {7170 for (c_source_files) |*item| {
...@@ -6917,9 +7172,7 @@ pub fn build_crt_file(...@@ -6917,9 +7172,7 @@ pub fn build_crt_file(
6917 }7172 }
69187173
6919 const sub_compilation = try Compilation.create(gpa, arena, .{7174 const sub_compilation = try Compilation.create(gpa, arena, .{
6920 .local_cache_directory = comp.global_cache_directory,7175 .dirs = comp.dirs.withoutLocalCache(),
6921 .global_cache_directory = comp.global_cache_directory,
6922 .zig_lib_directory = comp.zig_lib_directory,
6923 .self_exe_path = comp.self_exe_path,7176 .self_exe_path = comp.self_exe_path,
6924 .cache_mode = .whole,7177 .cache_mode = .whole,
6925 .config = config,7178 .config = config,
...@@ -6962,7 +7215,7 @@ pub fn build_crt_file(...@@ -6962,7 +7215,7 @@ pub fn build_crt_file(
6962 }7215 }
6963}7216}
69647217
6965pub fn queueLinkTaskMode(comp: *Compilation, path: Path, output_mode: std.builtin.OutputMode) void {7218pub fn queueLinkTaskMode(comp: *Compilation, path: Cache.Path, output_mode: std.builtin.OutputMode) void {
6966 comp.queueLinkTasks(switch (output_mode) {7219 comp.queueLinkTasks(switch (output_mode) {
6967 .Exe => unreachable,7220 .Exe => unreachable,
6968 .Obj => &.{.{ .load_object = path }},7221 .Obj => &.{.{ .load_object = path }},
...@@ -6983,7 +7236,7 @@ pub fn queueLinkTasks(comp: *Compilation, tasks: []const link.Task) void {...@@ -6983,7 +7236,7 @@ pub fn queueLinkTasks(comp: *Compilation, tasks: []const link.Task) void {
6983pub fn toCrtFile(comp: *Compilation) Allocator.Error!CrtFile {7236pub fn toCrtFile(comp: *Compilation) Allocator.Error!CrtFile {
6984 return .{7237 return .{
6985 .full_object_path = .{7238 .full_object_path = .{
6986 .root_dir = comp.local_cache_directory,7239 .root_dir = comp.dirs.local_cache,
6987 .sub_path = try comp.gpa.dupe(u8, comp.cache_use.whole.bin_sub_path.?),7240 .sub_path = try comp.gpa.dupe(u8, comp.cache_use.whole.bin_sub_path.?),
6988 },7241 },
6989 .lock = comp.cache_use.whole.moveLock(),7242 .lock = comp.cache_use.whole.moveLock(),
src/InternPool.zig+13
...@@ -1723,6 +1723,19 @@ pub const FileIndex = enum(u32) {...@@ -1723,6 +1723,19 @@ pub const FileIndex = enum(u32) {
1723 .index = @intFromEnum(file_index) & ip.getIndexMask(u32),1723 .index = @intFromEnum(file_index) & ip.getIndexMask(u32),
1724 };1724 };
1725 }1725 }
1726 pub fn toOptional(i: FileIndex) Optional {
1727 return @enumFromInt(@intFromEnum(i));
1728 }
1729 pub const Optional = enum(u32) {
1730 none = std.math.maxInt(u32),
1731 _,
1732 pub fn unwrap(opt: Optional) ?FileIndex {
1733 return switch (opt) {
1734 .none => null,
1735 _ => @enumFromInt(@intFromEnum(opt)),
1736 };
1737 }
1738 };
1726};1739};
17271740
1728const File = struct {1741const File = struct {
src/Package/Module.zig+74-148
...@@ -1,15 +1,17 @@...@@ -1,15 +1,17 @@
1//! Corresponds to something that Zig source code can `@import`.1//! Corresponds to something that Zig source code can `@import`.
22
3/// Only files inside this directory can be imported.3/// The root directory of the module. Only files inside this directory can be imported.
4root: Cache.Path,4root: Compilation.Path,
5/// Relative to `root`. May contain path separators.5/// Path to the root source file of this module. Relative to `root`. May contain path separators.
6root_src_path: []const u8,6root_src_path: []const u8,
7/// Name used in compile errors. Looks like "root.foo.bar".7/// Name used in compile errors. Looks like "root.foo.bar".
8fully_qualified_name: []const u8,8fully_qualified_name: []const u8,
9/// The dependency table of this module. Shared dependencies such as 'std',9/// The dependency table of this module. The shared dependencies 'std' and
10/// 'builtin', and 'root' are not specified in every dependency table, but10/// 'root' are not specified in every module dependency table, but are stored
11/// instead only in the table of `main_mod`. `Module.importFile` is11/// separately in `Zcu`. 'builtin' is also not stored here, although it is
12/// responsible for detecting these names and using the correct package.12/// not necessarily the same between all modules. Handling of `@import` in
13/// the rest of the compiler must detect these special names and use the
14/// correct module instead of consulting `deps`.
13deps: Deps = .{},15deps: Deps = .{},
1416
15resolved_target: ResolvedTarget,17resolved_target: ResolvedTarget,
...@@ -33,25 +35,14 @@ cc_argv: []const []const u8,...@@ -33,25 +35,14 @@ cc_argv: []const []const u8,
33structured_cfg: bool,35structured_cfg: bool,
34no_builtin: bool,36no_builtin: bool,
3537
36/// If the module is an `@import("builtin")` module, this is the `File` that
37/// is preallocated for it. Otherwise this field is null.
38builtin_file: ?*File,
39
40pub const Deps = std.StringArrayHashMapUnmanaged(*Module);38pub const Deps = std.StringArrayHashMapUnmanaged(*Module);
4139
42pub fn isBuiltin(m: Module) bool {
43 return m.builtin_file != null;
44}
45
46pub const Tree = struct {40pub const Tree = struct {
47 /// Each `Package` exposes a `Module` with build.zig as its root source file.41 /// Each `Package` exposes a `Module` with build.zig as its root source file.
48 build_module_table: std.AutoArrayHashMapUnmanaged(MultiHashHexDigest, *Module),42 build_module_table: std.AutoArrayHashMapUnmanaged(MultiHashHexDigest, *Module),
49};43};
5044
51pub const CreateOptions = struct {45pub const CreateOptions = struct {
52 /// Where to store builtin.zig. The global cache directory is used because
53 /// it is a pure function based on CLI flags.
54 global_cache_directory: Cache.Directory,
55 paths: Paths,46 paths: Paths,
56 fully_qualified_name: []const u8,47 fully_qualified_name: []const u8,
5748
...@@ -61,15 +52,8 @@ pub const CreateOptions = struct {...@@ -61,15 +52,8 @@ pub const CreateOptions = struct {
61 /// If this is null then `resolved_target` must be non-null.52 /// If this is null then `resolved_target` must be non-null.
62 parent: ?*Package.Module,53 parent: ?*Package.Module,
6354
64 builtin_mod: ?*Package.Module,
65
66 /// Allocated into the given `arena`. Should be shared across all module creations in a Compilation.
67 /// Ignored if `builtin_mod` is passed or if `!have_zcu`.
68 /// Otherwise, may be `null` only if this Compilation consists of a single module.
69 builtin_modules: ?*std.StringHashMapUnmanaged(*Module),
70
71 pub const Paths = struct {55 pub const Paths = struct {
72 root: Cache.Path,56 root: Compilation.Path,
73 /// Relative to `root`. May contain path separators.57 /// Relative to `root`. May contain path separators.
74 root_src_path: []const u8,58 root_src_path: []const u8,
75 };59 };
...@@ -401,126 +385,13 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Package.Module {...@@ -401,126 +385,13 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Package.Module {
401 .cc_argv = options.cc_argv,385 .cc_argv = options.cc_argv,
402 .structured_cfg = structured_cfg,386 .structured_cfg = structured_cfg,
403 .no_builtin = no_builtin,387 .no_builtin = no_builtin,
404 .builtin_file = null,
405 };388 };
406
407 const opt_builtin_mod = options.builtin_mod orelse b: {
408 if (!options.global.have_zcu) break :b null;
409
410 const generated_builtin_source = try Builtin.generate(.{
411 .target = target,
412 .zig_backend = zig_backend,
413 .output_mode = options.global.output_mode,
414 .link_mode = options.global.link_mode,
415 .unwind_tables = unwind_tables,
416 .is_test = options.global.is_test,
417 .single_threaded = single_threaded,
418 .link_libc = options.global.link_libc,
419 .link_libcpp = options.global.link_libcpp,
420 .optimize_mode = optimize_mode,
421 .error_tracing = error_tracing,
422 .valgrind = valgrind,
423 .sanitize_thread = sanitize_thread,
424 .fuzz = fuzz,
425 .pic = pic,
426 .pie = options.global.pie,
427 .strip = strip,
428 .code_model = code_model,
429 .omit_frame_pointer = omit_frame_pointer,
430 .wasi_exec_model = options.global.wasi_exec_model,
431 }, arena);
432
433 const new = if (options.builtin_modules) |builtins| new: {
434 const gop = try builtins.getOrPut(arena, generated_builtin_source);
435 if (gop.found_existing) break :b gop.value_ptr.*;
436 errdefer builtins.removeByPtr(gop.key_ptr);
437 const new = try arena.create(Module);
438 gop.value_ptr.* = new;
439 break :new new;
440 } else try arena.create(Module);
441 errdefer if (options.builtin_modules) |builtins| assert(builtins.remove(generated_builtin_source));
442
443 const new_file = try arena.create(File);
444
445 const hex_digest = digest: {
446 var hasher: Cache.Hasher = Cache.hasher_init;
447 hasher.update(generated_builtin_source);
448
449 var bin_digest: Cache.BinDigest = undefined;
450 hasher.final(&bin_digest);
451
452 var hex_digest: Cache.HexDigest = undefined;
453 _ = std.fmt.bufPrint(
454 &hex_digest,
455 "{s}",
456 .{std.fmt.fmtSliceHexLower(&bin_digest)},
457 ) catch unreachable;
458
459 break :digest hex_digest;
460 };
461
462 const builtin_sub_path = try arena.dupe(u8, "b" ++ std.fs.path.sep_str ++ hex_digest);
463
464 new.* = .{
465 .root = .{
466 .root_dir = options.global_cache_directory,
467 .sub_path = builtin_sub_path,
468 },
469 .root_src_path = "builtin.zig",
470 .fully_qualified_name = if (options.parent == null)
471 "builtin"
472 else
473 try std.fmt.allocPrint(arena, "{s}.builtin", .{options.fully_qualified_name}),
474 .resolved_target = .{
475 .result = target,
476 .is_native_os = resolved_target.is_native_os,
477 .is_native_abi = resolved_target.is_native_abi,
478 .llvm_cpu_features = llvm_cpu_features,
479 },
480 .optimize_mode = optimize_mode,
481 .single_threaded = single_threaded,
482 .error_tracing = error_tracing,
483 .valgrind = valgrind,
484 .pic = pic,
485 .strip = strip,
486 .omit_frame_pointer = omit_frame_pointer,
487 .stack_check = stack_check,
488 .stack_protector = stack_protector,
489 .code_model = code_model,
490 .red_zone = red_zone,
491 .sanitize_c = sanitize_c,
492 .sanitize_thread = sanitize_thread,
493 .fuzz = fuzz,
494 .unwind_tables = unwind_tables,
495 .cc_argv = &.{},
496 .structured_cfg = structured_cfg,
497 .no_builtin = no_builtin,
498 .builtin_file = new_file,
499 };
500 new_file.* = .{
501 .sub_file_path = "builtin.zig",
502 .stat = undefined,
503 .source = generated_builtin_source,
504 .tree = null,
505 .zir = null,
506 .zoir = null,
507 .status = .never_loaded,
508 .mod = new,
509 };
510 break :b new;
511 };
512
513 if (opt_builtin_mod) |builtin_mod| {
514 try mod.deps.ensureUnusedCapacity(arena, 1);
515 mod.deps.putAssumeCapacityNoClobber("builtin", builtin_mod);
516 }
517
518 return mod;389 return mod;
519}390}
520391
521/// All fields correspond to `CreateOptions`.392/// All fields correspond to `CreateOptions`.
522pub const LimitedOptions = struct {393pub const LimitedOptions = struct {
523 root: Cache.Path,394 root: Compilation.Path,
524 root_src_path: []const u8,395 root_src_path: []const u8,
525 fully_qualified_name: []const u8,396 fully_qualified_name: []const u8,
526};397};
...@@ -553,18 +424,73 @@ pub fn createLimited(gpa: Allocator, options: LimitedOptions) Allocator.Error!*P...@@ -553,18 +424,73 @@ pub fn createLimited(gpa: Allocator, options: LimitedOptions) Allocator.Error!*P
553 .cc_argv = undefined,424 .cc_argv = undefined,
554 .structured_cfg = undefined,425 .structured_cfg = undefined,
555 .no_builtin = undefined,426 .no_builtin = undefined,
556 .builtin_file = null,
557 };427 };
558 return mod;428 return mod;
559}429}
560430
561/// Asserts that the module has a builtin module, which is not true for non-zig431/// Does not ensure that the module's root directory exists on-disk; see `Builtin.updateFileOnDisk` for that task.
562/// modules such as ones only used for `@embedFile`, or the root module when432pub fn createBuiltin(arena: Allocator, opts: Builtin, dirs: Compilation.Directories) Allocator.Error!*Module {
563/// there is no Zig Compilation Unit.433 const sub_path = "b" ++ Cache.binToHex(opts.hash());
564pub fn getBuiltinDependency(m: Module) *Module {434 const new = try arena.create(Module);
565 const result = m.deps.values()[0];435 new.* = .{
566 assert(result.isBuiltin());436 .root = try .fromRoot(arena, dirs, .global_cache, sub_path),
567 return result;437 .root_src_path = "builtin.zig",
438 .fully_qualified_name = "builtin",
439 .resolved_target = .{
440 .result = opts.target,
441 // These values are not in `opts`, but do not matter because `builtin.zig` contains no runtime code.
442 .is_native_os = false,
443 .is_native_abi = false,
444 .llvm_cpu_features = null,
445 },
446 .optimize_mode = opts.optimize_mode,
447 .single_threaded = opts.single_threaded,
448 .error_tracing = opts.error_tracing,
449 .valgrind = opts.valgrind,
450 .pic = opts.pic,
451 .strip = opts.strip,
452 .omit_frame_pointer = opts.omit_frame_pointer,
453 .code_model = opts.code_model,
454 .sanitize_thread = opts.sanitize_thread,
455 .fuzz = opts.fuzz,
456 .unwind_tables = opts.unwind_tables,
457 .cc_argv = &.{},
458 // These values are not in `opts`, but do not matter because `builtin.zig` contains no runtime code.
459 .stack_check = false,
460 .stack_protector = 0,
461 .red_zone = false,
462 .sanitize_c = .off,
463 .structured_cfg = false,
464 .no_builtin = false,
465 };
466 return new;
467}
468
469/// Returns the `Builtin` which forms the contents of `@import("builtin")` for this module.
470pub fn getBuiltinOptions(m: Module, global: Compilation.Config) Builtin {
471 assert(global.have_zcu);
472 return .{
473 .target = m.resolved_target.result,
474 .zig_backend = target_util.zigBackend(m.resolved_target.result, global.use_llvm),
475 .output_mode = global.output_mode,
476 .link_mode = global.link_mode,
477 .unwind_tables = m.unwind_tables,
478 .is_test = global.is_test,
479 .single_threaded = m.single_threaded,
480 .link_libc = global.link_libc,
481 .link_libcpp = global.link_libcpp,
482 .optimize_mode = m.optimize_mode,
483 .error_tracing = m.error_tracing,
484 .valgrind = m.valgrind,
485 .sanitize_thread = m.sanitize_thread,
486 .fuzz = m.fuzz,
487 .pic = m.pic,
488 .pie = global.pie,
489 .strip = m.strip,
490 .code_model = m.code_model,
491 .omit_frame_pointer = m.omit_frame_pointer,
492 .wasi_exec_model = global.wasi_exec_model,
493 };
568}494}
569495
570const Module = @This();496const Module = @This();
src/Sema.zig+81-70
...@@ -829,7 +829,7 @@ pub const Block = struct {...@@ -829,7 +829,7 @@ pub const Block = struct {
829829
830 pub fn ownerModule(block: Block) *Package.Module {830 pub fn ownerModule(block: Block) *Package.Module {
831 const zcu = block.sema.pt.zcu;831 const zcu = block.sema.pt.zcu;
832 return zcu.namespacePtr(block.namespace).fileScope(zcu).mod;832 return zcu.namespacePtr(block.namespace).fileScope(zcu).mod.?;
833 }833 }
834834
835 fn trackZir(block: *Block, inst: Zir.Inst.Index) Allocator.Error!InternPool.TrackedInst.Index {835 fn trackZir(block: *Block, inst: Zir.Inst.Index) Allocator.Error!InternPool.TrackedInst.Index {
...@@ -1127,10 +1127,10 @@ fn analyzeBodyInner(...@@ -1127,10 +1127,10 @@ fn analyzeBodyInner(
11271127
1128 // The hashmap lookup in here is a little expensive, and LLVM fails to optimize it away.1128 // The hashmap lookup in here is a little expensive, and LLVM fails to optimize it away.
1129 if (build_options.enable_logging) {1129 if (build_options.enable_logging) {
1130 std.log.scoped(.sema_zir).debug("sema ZIR {s} %{d}", .{ sub_file_path: {1130 std.log.scoped(.sema_zir).debug("sema ZIR {} %{d}", .{ path: {
1131 const file_index = block.src_base_inst.resolveFile(&zcu.intern_pool);1131 const file_index = block.src_base_inst.resolveFile(&zcu.intern_pool);
1132 const file = zcu.fileByIndex(file_index);1132 const file = zcu.fileByIndex(file_index);
1133 break :sub_file_path file.sub_file_path;1133 break :path file.path.fmt(zcu.comp);
1134 }, inst });1134 }, inst });
1135 }1135 }
11361136
...@@ -6162,50 +6162,67 @@ fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileEr...@@ -6162,50 +6162,67 @@ fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileEr
6162 }6162 }
6163 const parent_mod = parent_block.ownerModule();6163 const parent_mod = parent_block.ownerModule();
6164 const digest = Cache.binToHex(c_import_res.digest);6164 const digest = Cache.binToHex(c_import_res.digest);
6165 const c_import_zig_path = try comp.arena.dupe(u8, "o" ++ std.fs.path.sep_str ++ digest);
6166 const c_import_mod = Package.Module.create(comp.arena, .{
6167 .global_cache_directory = comp.global_cache_directory,
6168 .paths = .{
6169 .root = .{
6170 .root_dir = comp.local_cache_directory,
6171 .sub_path = c_import_zig_path,
6172 },
6173 .root_src_path = "cimport.zig",
6174 },
6175 .fully_qualified_name = c_import_zig_path,
6176 .cc_argv = parent_mod.cc_argv,
6177 .inherited = .{},
6178 .global = comp.config,
6179 .parent = parent_mod,
6180 .builtin_mod = parent_mod.getBuiltinDependency(),
6181 .builtin_modules = null, // `builtin_mod` is set
6182 }) catch |err| switch (err) {
6183 // None of these are possible because we are creating a package with
6184 // the exact same configuration as the parent package, which already
6185 // passed these checks.
6186 error.ValgrindUnsupportedOnTarget => unreachable,
6187 error.TargetRequiresSingleThreaded => unreachable,
6188 error.BackendRequiresSingleThreaded => unreachable,
6189 error.TargetRequiresPic => unreachable,
6190 error.PieRequiresPic => unreachable,
6191 error.DynamicLinkingRequiresPic => unreachable,
6192 error.TargetHasNoRedZone => unreachable,
6193 error.StackCheckUnsupportedByTarget => unreachable,
6194 error.StackProtectorUnsupportedByTarget => unreachable,
6195 error.StackProtectorUnavailableWithoutLibC => unreachable,
61966165
6197 else => |e| return e,6166 const new_file_index = file: {
6198 };6167 const c_import_zig_path = try comp.arena.dupe(u8, "o" ++ std.fs.path.sep_str ++ digest);
6168 const c_import_mod = Package.Module.create(comp.arena, .{
6169 .paths = .{
6170 .root = try .fromRoot(comp.arena, comp.dirs, .local_cache, c_import_zig_path),
6171 .root_src_path = "cimport.zig",
6172 },
6173 .fully_qualified_name = c_import_zig_path,
6174 .cc_argv = parent_mod.cc_argv,
6175 .inherited = .{},
6176 .global = comp.config,
6177 .parent = parent_mod,
6178 }) catch |err| switch (err) {
6179 // None of these are possible because we are creating a package with
6180 // the exact same configuration as the parent package, which already
6181 // passed these checks.
6182 error.ValgrindUnsupportedOnTarget => unreachable,
6183 error.TargetRequiresSingleThreaded => unreachable,
6184 error.BackendRequiresSingleThreaded => unreachable,
6185 error.TargetRequiresPic => unreachable,
6186 error.PieRequiresPic => unreachable,
6187 error.DynamicLinkingRequiresPic => unreachable,
6188 error.TargetHasNoRedZone => unreachable,
6189 error.StackCheckUnsupportedByTarget => unreachable,
6190 error.StackProtectorUnsupportedByTarget => unreachable,
6191 error.StackProtectorUnavailableWithoutLibC => unreachable,
61996192
6200 const result = pt.importPkg(c_import_mod) catch |err|6193 else => |e| return e,
6201 return sema.fail(&child_block, src, "C import failed: {s}", .{@errorName(err)});6194 };
62026195 const c_import_file_path: Compilation.Path = try c_import_mod.root.join(gpa, comp.dirs, "cimport.zig");
6203 const path_digest = zcu.filePathDigest(result.file_index);6196 errdefer c_import_file_path.deinit(gpa);
6204 pt.updateFile(result.file, path_digest) catch |err|6197 const c_import_file = try gpa.create(Zcu.File);
6198 errdefer gpa.destroy(c_import_file);
6199 const c_import_file_index = try zcu.intern_pool.createFile(gpa, pt.tid, .{
6200 .bin_digest = c_import_file_path.digest(),
6201 .file = c_import_file,
6202 .root_type = .none,
6203 });
6204 c_import_file.* = .{
6205 .status = .never_loaded,
6206 .stat = undefined,
6207 .is_builtin = false,
6208 .path = c_import_file_path,
6209 .source = null,
6210 .tree = null,
6211 .zir = null,
6212 .zoir = null,
6213 .mod = c_import_mod,
6214 .sub_file_path = "cimport.zig",
6215 .module_changed = false,
6216 .prev_zir = null,
6217 .zoir_invalidated = false,
6218 };
6219 break :file c_import_file_index;
6220 };
6221 pt.updateFile(new_file_index, zcu.fileByIndex(new_file_index)) catch |err|
6205 return sema.fail(&child_block, src, "C import failed: {s}", .{@errorName(err)});6222 return sema.fail(&child_block, src, "C import failed: {s}", .{@errorName(err)});
62066223
6207 try pt.ensureFileAnalyzed(result.file_index);6224 try pt.ensureFileAnalyzed(new_file_index);
6208 const ty = zcu.fileRootType(result.file_index);6225 const ty = zcu.fileRootType(new_file_index);
6209 try sema.declareDependency(.{ .interned = ty });6226 try sema.declareDependency(.{ .interned = ty });
6210 try sema.addTypeReferenceEntry(src, ty);6227 try sema.addTypeReferenceEntry(src, ty);
6211 return Air.internedToRef(ty);6228 return Air.internedToRef(ty);
...@@ -14097,25 +14114,19 @@ fn zirImport(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air....@@ -14097,25 +14114,19 @@ fn zirImport(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
14097 const operand_src = block.tokenOffset(inst_data.src_tok);14114 const operand_src = block.tokenOffset(inst_data.src_tok);
14098 const operand = sema.code.nullTerminatedString(extra.path);14115 const operand = sema.code.nullTerminatedString(extra.path);
1409914116
14100 const result = pt.importFile(block.getFileScope(zcu), operand) catch |err| switch (err) {14117 const result = pt.doImport(block.getFileScope(zcu), operand) catch |err| switch (err) {
14101 error.ImportOutsideModulePath => {14118 error.ModuleNotFound => return sema.fail(block, operand_src, "no module named '{s}' available within module '{s}'", .{
14102 return sema.fail(block, operand_src, "import of file outside module path: '{s}'", .{operand});14119 operand, block.getFileScope(zcu).mod.?.fully_qualified_name,
14103 },14120 }),
14104 error.ModuleNotFound => {14121 error.IllegalZigImport => unreachable, // caught before semantic analysis
14105 return sema.fail(block, operand_src, "no module named '{s}' available within module {s}", .{14122 error.OutOfMemory => |e| return e,
14106 operand, block.getFileScope(zcu).mod.fully_qualified_name,
14107 });
14108 },
14109 else => {
14110 // TODO: these errors are file system errors; make sure an update() will
14111 // retry this and not cache the file system error, which may be transient.
14112 return sema.fail(block, operand_src, "unable to open '{s}': {s}", .{ operand, @errorName(err) });
14113 },
14114 };14123 };
14115 switch (result.file.getMode()) {14124 const file_index = result.file;
14125 const file = zcu.fileByIndex(file_index);
14126 switch (file.getMode()) {
14116 .zig => {14127 .zig => {
14117 try pt.ensureFileAnalyzed(result.file_index);14128 try pt.ensureFileAnalyzed(file_index);
14118 const ty = zcu.fileRootType(result.file_index);14129 const ty = zcu.fileRootType(file_index);
14119 try sema.declareDependency(.{ .interned = ty });14130 try sema.declareDependency(.{ .interned = ty });
14120 try sema.addTypeReferenceEntry(operand_src, ty);14131 try sema.addTypeReferenceEntry(operand_src, ty);
14121 return Air.internedToRef(ty);14132 return Air.internedToRef(ty);
...@@ -14129,11 +14140,11 @@ fn zirImport(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air....@@ -14129,11 +14140,11 @@ fn zirImport(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
14129 break :b res_ty.toIntern();14140 break :b res_ty.toIntern();
14130 };14141 };
1413114142
14132 try sema.declareDependency(.{ .zon_file = result.file_index });14143 try sema.declareDependency(.{ .zon_file = file_index });
14133 const interned = try LowerZon.run(14144 const interned = try LowerZon.run(
14134 sema,14145 sema,
14135 result.file,14146 file,
14136 result.file_index,14147 file_index,
14137 res_ty,14148 res_ty,
14138 operand_src,14149 operand_src,
14139 block,14150 block,
...@@ -17308,10 +17319,10 @@ fn zirClosureGet(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat...@@ -17308,10 +17319,10 @@ fn zirClosureGet(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat
17308 const name = name: {17319 const name = name: {
17309 // TODO: we should probably store this name in the ZIR to avoid this complexity.17320 // TODO: we should probably store this name in the ZIR to avoid this complexity.
17310 const file, const src_base_node = Zcu.LazySrcLoc.resolveBaseNode(block.src_base_inst, zcu).?;17321 const file, const src_base_node = Zcu.LazySrcLoc.resolveBaseNode(block.src_base_inst, zcu).?;
17311 const tree = file.getTree(sema.gpa) catch |err| {17322 const tree = file.getTree(zcu) catch |err| {
17312 // In this case we emit a warning + a less precise source location.17323 // In this case we emit a warning + a less precise source location.
17313 log.warn("unable to load {s}: {s}", .{17324 log.warn("unable to load {}: {s}", .{
17314 file.sub_file_path, @errorName(err),17325 file.path.fmt(zcu.comp), @errorName(err),
17315 });17326 });
17316 break :name null;17327 break :name null;
17317 };17328 };
...@@ -17336,10 +17347,10 @@ fn zirClosureGet(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat...@@ -17336,10 +17347,10 @@ fn zirClosureGet(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat
17336 const msg = msg: {17347 const msg = msg: {
17337 const name = name: {17348 const name = name: {
17338 const file, const src_base_node = Zcu.LazySrcLoc.resolveBaseNode(block.src_base_inst, zcu).?;17349 const file, const src_base_node = Zcu.LazySrcLoc.resolveBaseNode(block.src_base_inst, zcu).?;
17339 const tree = file.getTree(sema.gpa) catch |err| {17350 const tree = file.getTree(zcu) catch |err| {
17340 // In this case we emit a warning + a less precise source location.17351 // In this case we emit a warning + a less precise source location.
17341 log.warn("unable to load {s}: {s}", .{17352 log.warn("unable to load {}: {s}", .{
17342 file.sub_file_path, @errorName(err),17353 file.path.fmt(zcu.comp), @errorName(err),
17343 });17354 });
17344 break :name null;17355 break :name null;
17345 };17356 };
...@@ -17433,7 +17444,7 @@ fn zirBuiltinSrc(...@@ -17433,7 +17444,7 @@ fn zirBuiltinSrc(
17433 };17444 };
1743417445
17435 const module_name_val = v: {17446 const module_name_val = v: {
17436 const module_name = file_scope.mod.fully_qualified_name;17447 const module_name = file_scope.mod.?.fully_qualified_name;
17437 const array_ty = try pt.intern(.{ .array_type = .{17448 const array_ty = try pt.intern(.{ .array_type = .{
17438 .len = module_name.len,17449 .len = module_name.len,
17439 .sentinel = .zero_u8,17450 .sentinel = .zero_u8,
src/Zcu.zig+441-262
...@@ -72,9 +72,9 @@ sema_prog_node: std.Progress.Node = std.Progress.Node.none,...@@ -72,9 +72,9 @@ sema_prog_node: std.Progress.Node = std.Progress.Node.none,
72codegen_prog_node: std.Progress.Node = std.Progress.Node.none,72codegen_prog_node: std.Progress.Node = std.Progress.Node.none,
7373
74/// Used by AstGen worker to load and store ZIR cache.74/// Used by AstGen worker to load and store ZIR cache.
75global_zir_cache: Compilation.Directory,75global_zir_cache: Cache.Directory,
76/// Used by AstGen worker to load and store ZIR cache.76/// Used by AstGen worker to load and store ZIR cache.
77local_zir_cache: Compilation.Directory,77local_zir_cache: Cache.Directory,
7878
79/// This is where all `Export` values are stored. Not all values here are necessarily valid exports;79/// This is where all `Export` values are stored. Not all values here are necessarily valid exports;
80/// to enumerate all exports, `single_exports` and `multi_exports` must be consulted.80/// to enumerate all exports, `single_exports` and `multi_exports` must be consulted.
...@@ -93,27 +93,72 @@ multi_exports: std.AutoArrayHashMapUnmanaged(AnalUnit, extern struct {...@@ -93,27 +93,72 @@ multi_exports: std.AutoArrayHashMapUnmanaged(AnalUnit, extern struct {
93 len: u32,93 len: u32,
94}) = .{},94}) = .{},
9595
96/// Key is the digest returned by `Builtin.hash`; value is the corresponding module.
97builtin_modules: std.AutoArrayHashMapUnmanaged(Cache.BinDigest, *Package.Module) = .empty,
98
99/// Populated as soon as the `Compilation` is created. Guaranteed to contain all modules, even builtin ones.
100/// Modules whose root file is not a Zig or ZON file have the value `.none`.
101module_roots: std.AutoArrayHashMapUnmanaged(*Package.Module, File.Index.Optional) = .empty,
102
96/// The set of all the Zig source files in the Zig Compilation Unit. Tracked in103/// The set of all the Zig source files in the Zig Compilation Unit. Tracked in
97/// order to iterate over it and check which source files have been modified on104/// order to iterate over it and check which source files have been modified on
98/// the file system when an update is requested, as well as to cache `@import`105/// the file system when an update is requested, as well as to cache `@import`
99/// results.106/// results.
100///107///
101/// Keys are fully resolved file paths. This table owns the keys and values.108/// Always accessed through `ImportTableAdapter`, where keys are fully resolved
109/// file paths in order to ensure files are properly deduplicated. This table owns
110/// the keys and values.
102///111///
103/// Protected by Compilation's mutex.112/// Protected by Compilation's mutex.
104///113///
105/// Not serialized. This state is reconstructed during the first call to114/// Not serialized. This state is reconstructed during the first call to
106/// `Compilation.update` of the process for a given `Compilation`.115/// `Compilation.update` of the process for a given `Compilation`.
107///116import_table: std.ArrayHashMapUnmanaged(
108/// Indexes correspond 1:1 to `files`.117 File.Index,
109import_table: std.StringArrayHashMapUnmanaged(File.Index) = .empty,118 void,
119 struct {
120 pub const hash = @compileError("all accesses should be through ImportTableAdapter");
121 pub const eql = @compileError("all accesses should be through ImportTableAdapter");
122 },
123 true, // This is necessary! Without it, the map tries to use its Context to rehash. #21918
124) = .empty,
125
126/// The set of all files in `import_table` which are "alive" this update, meaning
127/// they are reachable by traversing imports starting from an analysis root. This
128/// is usually all files in `import_table`, but some could be omitted if an incremental
129/// update removes an import, or if a module specified on the CLI is never imported.
130/// Reconstructed on every update, after AstGen and before Sema.
131/// Value is why the file is alive.
132alive_files: std.AutoArrayHashMapUnmanaged(File.Index, File.Reference) = .empty,
133
134/// If this is populated, a "file exists in multiple modules" error should be emitted.
135/// This causes file errors to not be shown, because we don't really know which files
136/// should be alive (because the user has messed up their imports somewhere!).
137/// Cleared and recomputed every update, after AstGen and before Sema.
138multi_module_err: ?struct {
139 file: File.Index,
140 modules: [2]*Package.Module,
141 refs: [2]File.Reference,
142} = null,
110143
111/// The set of all the files which have been loaded with `@embedFile` in the Module.144/// The set of all the files which have been loaded with `@embedFile` in the Module.
112/// We keep track of this in order to iterate over it and check which files have been145/// We keep track of this in order to iterate over it and check which files have been
113/// modified on the file system when an update is requested, as well as to cache146/// modified on the file system when an update is requested, as well as to cache
114/// `@embedFile` results.147/// `@embedFile` results.
115/// Keys are fully resolved file paths. This table owns the keys and values.148///
116embed_table: std.StringArrayHashMapUnmanaged(*EmbedFile) = .empty,149/// Like `import_table`, this is accessed through `EmbedTableAdapter`, so that it is keyed
150/// on the `Compilation.Path` of the `EmbedFile`.
151///
152/// This table owns all of the `*EmbedFile` memory, which is allocated into gpa.
153embed_table: std.ArrayHashMapUnmanaged(
154 *EmbedFile,
155 void,
156 struct {
157 pub const hash = @compileError("all accesses should be through EmbedTableAdapter");
158 pub const eql = @compileError("all accesses should be through EmbedTableAdapter");
159 },
160 true, // This is necessary! Without it, the map tries to use its Context to rehash. #21918
161) = .empty,
117162
118/// Stores all Type and Value objects.163/// Stores all Type and Value objects.
119/// The idea is that this will be periodically garbage-collected, but such logic164/// The idea is that this will be periodically garbage-collected, but such logic
...@@ -147,9 +192,41 @@ compile_logs: std.AutoArrayHashMapUnmanaged(AnalUnit, extern struct {...@@ -147,9 +192,41 @@ compile_logs: std.AutoArrayHashMapUnmanaged(AnalUnit, extern struct {
147}) = .empty,192}) = .empty,
148compile_log_lines: std.ArrayListUnmanaged(CompileLogLine) = .empty,193compile_log_lines: std.ArrayListUnmanaged(CompileLogLine) = .empty,
149free_compile_log_lines: std.ArrayListUnmanaged(CompileLogLine.Index) = .empty,194free_compile_log_lines: std.ArrayListUnmanaged(CompileLogLine.Index) = .empty,
150/// Using a map here for consistency with the other fields here.195/// This tracks files which triggered errors when generating AST/ZIR/ZOIR.
151/// The ErrorMsg memory is owned by the `File`, using Module's general purpose allocator.196/// If not `null`, the value is a retryable error (the file status is guaranteed
152failed_files: std.AutoArrayHashMapUnmanaged(*File, ?*ErrorMsg) = .empty,197/// to be `.retryable_failure`). Otherwise, the file status is `.astgen_failure`
198/// or `.success`, and there are ZIR/ZOIR errors which should be printed.
199/// We just store a `[]u8` instead of a full `*ErrorMsg`, because the source
200/// location is always the entire file. The `[]u8` memory is owned by the map
201/// and allocated into `gpa`.
202failed_files: std.AutoArrayHashMapUnmanaged(File.Index, ?[]u8) = .empty,
203/// AstGen is not aware of modules, and so cannot determine whether an import
204/// string makes sense. That is the job of a traversal after AstGen.
205///
206/// There are several ways in which an import can fail:
207///
208/// * It is an import of a file which does not exist. This case is not handled
209/// by this field, but with a `failed_files` entry on the *imported* file.
210/// * It is an import of a module which does not exist in the current module's
211/// dependency table. This happens at `Sema` time, so is not tracked by this
212/// field.
213/// * It is an import which reaches outside of the current module's root
214/// directory. This is tracked by this field.
215/// * It is an import which reaches into an "illegal import directory". Right now,
216/// the only such directory is 'global_cache/b/', but in general, these are
217/// directories the compiler treats specially. This is tracked by this field.
218///
219/// This is a flat array containing all of the relevant errors. It is cleared and
220/// recomputed on every update. The errors here are fatal, i.e. they block any
221/// semantic analysis this update.
222///
223/// Allocated into gpa.
224failed_imports: std.ArrayListUnmanaged(struct {
225 file_index: File.Index,
226 import_string: Zir.NullTerminatedString,
227 import_token: Ast.TokenIndex,
228 kind: enum { file_outside_module_root, illegal_zig_import },
229}) = .empty,
153failed_exports: std.AutoArrayHashMapUnmanaged(Export.Index, *ErrorMsg) = .empty,230failed_exports: std.AutoArrayHashMapUnmanaged(Export.Index, *ErrorMsg) = .empty,
154/// If analysis failed due to a cimport error, the corresponding Clang errors231/// If analysis failed due to a cimport error, the corresponding Clang errors
155/// are stored here.232/// are stored here.
...@@ -235,6 +312,32 @@ generation: u32 = 0,...@@ -235,6 +312,32 @@ generation: u32 = 0,
235312
236pub const PerThread = @import("Zcu/PerThread.zig");313pub const PerThread = @import("Zcu/PerThread.zig");
237314
315pub const ImportTableAdapter = struct {
316 zcu: *const Zcu,
317 pub fn hash(ctx: ImportTableAdapter, path: Compilation.Path) u32 {
318 _ = ctx;
319 return @truncate(std.hash.Wyhash.hash(@intFromEnum(path.root), path.sub_path));
320 }
321 pub fn eql(ctx: ImportTableAdapter, a_path: Compilation.Path, b_file: File.Index, b_index: usize) bool {
322 _ = b_index;
323 const b_path = ctx.zcu.fileByIndex(b_file).path;
324 return a_path.root == b_path.root and mem.eql(u8, a_path.sub_path, b_path.sub_path);
325 }
326};
327
328pub const EmbedTableAdapter = struct {
329 pub fn hash(ctx: EmbedTableAdapter, path: Compilation.Path) u32 {
330 _ = ctx;
331 return @truncate(std.hash.Wyhash.hash(@intFromEnum(path.root), path.sub_path));
332 }
333 pub fn eql(ctx: EmbedTableAdapter, a_path: Compilation.Path, b_file: *EmbedFile, b_index: usize) bool {
334 _ = ctx;
335 _ = b_index;
336 const b_path = b_file.path;
337 return a_path.root == b_path.root and mem.eql(u8, a_path.sub_path, b_path.sub_path);
338 }
339};
340
238/// Names of declarations in `std.builtin` whose values are memoized in a `BuiltinDecl.Memoized`.341/// Names of declarations in `std.builtin` whose values are memoized in a `BuiltinDecl.Memoized`.
239/// The name must exactly match the declaration name, as comptime logic is used to compute the namespace accesses.342/// The name must exactly match the declaration name, as comptime logic is used to compute the namespace accesses.
240/// Parent namespaces must be before their children in this enum. For instance, `.Type` must be before `.@"Type.Fn"`.343/// Parent namespaces must be before their children in this enum. For instance, `.Type` must be before `.@"Type.Fn"`.
...@@ -732,41 +835,61 @@ pub const Namespace = struct {...@@ -732,41 +835,61 @@ pub const Namespace = struct {
732};835};
733836
734pub const File = struct {837pub const File = struct {
735 /// Relative to the owning package's root source directory.
736 /// Memory is stored in gpa, owned by File.
737 sub_file_path: []const u8,
738
739 status: enum {838 status: enum {
740 /// We have not yet attempted to load this file.839 /// We have not yet attempted to load this file.
741 /// `stat` is not populated and may be `undefined`.840 /// `stat` is not populated and may be `undefined`.
742 never_loaded,841 never_loaded,
743 /// A filesystem access failed. It should be retried on the next update.842 /// A filesystem access failed. It should be retried on the next update.
744 /// There is a `failed_files` entry containing a non-`null` message.843 /// There is guaranteed to be a `failed_files` entry with at least one message.
844 /// ZIR/ZOIR errors should not be emitted as `zir`/`zoir` is not up-to-date.
745 /// `stat` is not populated and may be `undefined`.845 /// `stat` is not populated and may be `undefined`.
746 retryable_failure,846 retryable_failure,
747 /// Parsing/AstGen/ZonGen of this file has failed.847 /// This file has failed parsing, AstGen, or ZonGen.
748 /// There is an error in `zir` or `zoir`.848 /// There is guaranteed to be a `failed_files` entry, which may or may not have messages.
749 /// There is a `failed_files` entry (with a `null` message).849 /// ZIR/ZOIR errors *should* be emitted as `zir`/`zoir` is up-to-date.
750 /// `stat` is populated.850 /// `stat` is populated.
751 astgen_failure,851 astgen_failure,
752 /// Parsing and AstGen/ZonGen of this file has succeeded.852 /// Parsing and AstGen/ZonGen of this file has succeeded.
853 /// There may still be a `failed_files` entry, e.g. for non-fatal AstGen errors.
753 /// `stat` is populated.854 /// `stat` is populated.
754 success,855 success,
755 },856 },
756 /// Whether this is populated depends on `status`.857 /// Whether this is populated depends on `status`.
757 stat: Cache.File.Stat,858 stat: Cache.File.Stat,
758859
860 /// Whether this file is the generated file of a "builtin" module. This matters because those
861 /// files are generated and stored in-nemory rather than being read off-disk. The rest of the
862 /// pipeline generally shouldn't care about this.
863 is_builtin: bool,
864
865 /// The path of this file. It is important that this path has a "canonical form" because files
866 /// are deduplicated based on path; `Compilation.Path` guarantees this. Owned by this `File`,
867 /// allocated into `gpa`.
868 path: Compilation.Path,
869
759 source: ?[:0]const u8,870 source: ?[:0]const u8,
760 tree: ?Ast,871 tree: ?Ast,
761 zir: ?Zir,872 zir: ?Zir,
762 zoir: ?Zoir,873 zoir: ?Zoir,
763874
764 /// Module that this file is a part of, managed externally.875 /// Module that this file is a part of, managed externally.
765 mod: *Package.Module,876 /// This is initially `null`. After AstGen, a pass is run to determine which module each
766 /// Whether this file is a part of multiple packages. This is an error condition which will be reported after AstGen.877 /// file belongs to, at which point this field is set. It is never set to `null` again;
767 multi_pkg: bool = false,878 /// this is so that if the file starts belonging to a different module instead, we can
768 /// List of references to this file, used for multi-package errors.879 /// tell, and invalidate dependencies as needed (see `module_changed`).
769 references: std.ArrayListUnmanaged(File.Reference) = .empty,880 /// During semantic analysis, this is always non-`null` for alive files (i.e. those which
881 /// have imports targeting them).
882 mod: ?*Package.Module,
883 /// Relative to the root directory of `mod`. If `mod == null`, this field is `undefined`.
884 /// This memory is managed externally and must not be directly freed.
885 /// Its lifetime is at least equal to that of this `File`.
886 sub_file_path: []const u8,
887
888 /// If this file's module identity changes on an incremental update, this flag is set to signal
889 /// to `Zcu.updateZirRefs` that all references to this file must be invalidated. This matters
890 /// because changing your module changes things like your optimization mode and codegen flags,
891 /// so everything needs to be re-done. `updateZirRefs` is responsible for resetting this flag.
892 module_changed: bool,
770893
771 /// The ZIR for this file from the last update with no file failures. As such, this ZIR is never894 /// The ZIR for this file from the last update with no file failures. As such, this ZIR is never
772 /// failed (although it may have compile errors).895 /// failed (although it may have compile errors).
...@@ -777,7 +900,7 @@ pub const File = struct {...@@ -777,7 +900,7 @@ pub const File = struct {
777 ///900 ///
778 /// In other words, if `TrackedInst`s are tied to ZIR other than what's in the `zir` field, this901 /// In other words, if `TrackedInst`s are tied to ZIR other than what's in the `zir` field, this
779 /// field is populated with that old ZIR.902 /// field is populated with that old ZIR.
780 prev_zir: ?*Zir = null,903 prev_zir: ?*Zir,
781904
782 /// This field serves a similar purpose to `prev_zir`, but for ZOIR. However, since we do not905 /// This field serves a similar purpose to `prev_zir`, but for ZOIR. However, since we do not
783 /// need to map old ZOIR to new ZOIR -- instead only invalidating dependencies if the ZOIR906 /// need to map old ZOIR to new ZOIR -- instead only invalidating dependencies if the ZOIR
...@@ -785,27 +908,42 @@ pub const File = struct {...@@ -785,27 +908,42 @@ pub const File = struct {
785 ///908 ///
786 /// When `zoir` is updated, this field is set to `true`. In `updateZirRefs`, if this is `true`,909 /// When `zoir` is updated, this field is set to `true`. In `updateZirRefs`, if this is `true`,
787 /// we invalidate the corresponding `zon_file` dependency, and reset it to `false`.910 /// we invalidate the corresponding `zon_file` dependency, and reset it to `false`.
788 zoir_invalidated: bool = false,911 zoir_invalidated: bool,
912
913 pub const Path = struct {
914 root: enum {
915 cwd,
916 fs_root,
917 local_cache,
918 global_cache,
919 lib_dir,
920 },
921 };
789922
790 /// A single reference to a file.923 /// A single reference to a file.
791 pub const Reference = union(enum) {924 pub const Reference = union(enum) {
792 /// The file is imported directly (i.e. not as a package) with @import.925 analysis_root: *Package.Module,
793 import: struct {926 import: struct {
794 file: File.Index,927 importer: Zcu.File.Index,
795 token: Ast.TokenIndex,928 tok: Ast.TokenIndex,
929 /// If the file is imported as the root of a module, this is that module.
930 /// `null` means the file was imported directly by path.
931 module: ?*Package.Module,
796 },932 },
797 /// The file is the root of a module.
798 root: *Package.Module,
799 };933 };
800934
801 pub fn getMode(self: File) Ast.Mode {935 pub fn getMode(self: File) Ast.Mode {
802 if (std.mem.endsWith(u8, self.sub_file_path, ".zon")) {936 // We never create a `File` whose path doesn't give a mode.
937 return modeFromPath(self.path.sub_path).?;
938 }
939
940 pub fn modeFromPath(path: []const u8) ?Ast.Mode {
941 if (std.mem.endsWith(u8, path, ".zon")) {
803 return .zon;942 return .zon;
804 } else if (std.mem.endsWith(u8, self.sub_file_path, ".zig")) {943 } else if (std.mem.endsWith(u8, path, ".zig")) {
805 return .zig;944 return .zig;
806 } else {945 } else {
807 // `Module.importFile` rejects all other extensions946 return null;
808 unreachable;
809 }947 }
810 }948 }
811949
...@@ -842,15 +980,18 @@ pub const File = struct {...@@ -842,15 +980,18 @@ pub const File = struct {
842 stat: Cache.File.Stat,980 stat: Cache.File.Stat,
843 };981 };
844982
845 pub fn getSource(file: *File, gpa: Allocator) !Source {983 pub fn getSource(file: *File, zcu: *const Zcu) !Source {
984 const gpa = zcu.gpa;
985
846 if (file.source) |source| return .{986 if (file.source) |source| return .{
847 .bytes = source,987 .bytes = source,
848 .stat = file.stat,988 .stat = file.stat,
849 };989 };
850990
851 // Keep track of inode, file size, mtime, hash so we can detect which files991 var f = f: {
852 // have been modified when an incremental update is requested.992 const dir, const sub_path = file.path.openInfo(zcu.comp.dirs);
853 var f = try file.mod.root.openFile(file.sub_file_path, .{});993 break :f try dir.openFile(sub_path, .{});
994 };
854 defer f.close();995 defer f.close();
855996
856 const stat = try f.stat();997 const stat = try f.stat();
...@@ -882,28 +1023,14 @@ pub const File = struct {...@@ -882,28 +1023,14 @@ pub const File = struct {
882 };1023 };
883 }1024 }
8841025
885 pub fn getTree(file: *File, gpa: Allocator) !*const Ast {1026 pub fn getTree(file: *File, zcu: *const Zcu) !*const Ast {
886 if (file.tree) |*tree| return tree;1027 if (file.tree) |*tree| return tree;
8871028
888 const source = try file.getSource(gpa);1029 const source = try file.getSource(zcu);
889 file.tree = try .parse(gpa, source.bytes, file.getMode());1030 file.tree = try .parse(zcu.gpa, source.bytes, file.getMode());
890 return &file.tree.?;1031 return &file.tree.?;
891 }1032 }
8921033
893 pub fn getZoir(file: *File, zcu: *Zcu) !*const Zoir {
894 if (file.zoir) |*zoir| return zoir;
895
896 const tree = file.tree.?;
897 assert(tree.mode == .zon);
898
899 file.zoir = try ZonGen.generate(zcu.gpa, tree, .{});
900 if (file.zoir.?.hasCompileErrors()) {
901 try zcu.failed_files.putNoClobber(zcu.gpa, file, null);
902 return error.AnalysisFail;
903 }
904 return &file.zoir.?;
905 }
906
907 pub fn fullyQualifiedNameLen(file: File) usize {1034 pub fn fullyQualifiedNameLen(file: File) usize {
908 const ext = std.fs.path.extension(file.sub_file_path);1035 const ext = std.fs.path.extension(file.sub_file_path);
909 return file.sub_file_path.len - ext.len;1036 return file.sub_file_path.len - ext.len;
...@@ -937,85 +1064,49 @@ pub const File = struct {...@@ -937,85 +1064,49 @@ pub const File = struct {
937 return ip.getOrPutTrailingString(gpa, pt.tid, @intCast(slice[0].len), .no_embedded_nulls);1064 return ip.getOrPutTrailingString(gpa, pt.tid, @intCast(slice[0].len), .no_embedded_nulls);
938 }1065 }
9391066
940 pub fn fullPath(file: File, ally: Allocator) ![]u8 {1067 pub const Index = InternPool.FileIndex;
941 return file.mod.root.joinString(ally, file.sub_file_path);
942 }
943
944 pub fn dumpSrc(file: *File, src: LazySrcLoc) void {
945 const loc = std.zig.findLineColumn(file.source.bytes, src);
946 std.debug.print("{s}:{d}:{d}\n", .{ file.sub_file_path, loc.line + 1, loc.column + 1 });
947 }
948
949 /// Add a reference to this file during AstGen.
950 pub fn addReference(file: *File, zcu: *Zcu, ref: File.Reference) !void {
951 // Don't add the same module root twice. Note that since we always add module roots at the
952 // front of the references array (see below), this loop is actually O(1) on valid code.
953 if (ref == .root) {
954 for (file.references.items) |other| {
955 switch (other) {
956 .root => |r| if (ref.root == r) return,
957 else => break, // reached the end of the "is-root" references
958 }
959 }
960 }
961
962 switch (ref) {
963 // We put root references at the front of the list both to make the above loop fast and
964 // to make multi-module errors more helpful (since "root-of" notes are generally more
965 // informative than "imported-from" notes). This path is hit very rarely, so the speed
966 // of the insert operation doesn't matter too much.
967 .root => try file.references.insert(zcu.gpa, 0, ref),
968
969 // Other references we'll just put at the end.
970 else => try file.references.append(zcu.gpa, ref),
971 }
9721068
973 const mod = switch (ref) {1069 pub fn errorBundleWholeFileSrc(
974 .import => |import| zcu.fileByIndex(import.file).mod,1070 file: *File,
975 .root => |mod| mod,1071 zcu: *const Zcu,
976 };1072 eb: *std.zig.ErrorBundle.Wip,
977 if (mod != file.mod) file.multi_pkg = true;1073 ) !std.zig.ErrorBundle.SourceLocationIndex {
1074 return eb.addSourceLocation(.{
1075 .src_path = try eb.printString("{}", .{file.path.fmt(zcu.comp)}),
1076 .span_start = 0,
1077 .span_main = 0,
1078 .span_end = 0,
1079 .line = 0,
1080 .column = 0,
1081 .source_line = 0,
1082 });
978 }1083 }
9791084 pub fn errorBundleTokenSrc(
980 /// Mark this file and every file referenced by it as multi_pkg and report an1085 file: *File,
981 /// astgen_failure error for them. AstGen must have completed in its entirety.1086 tok: Ast.TokenIndex,
982 pub fn recursiveMarkMultiPkg(file: *File, pt: Zcu.PerThread) void {1087 zcu: *const Zcu,
983 file.multi_pkg = true;1088 eb: *std.zig.ErrorBundle.Wip,
984 file.status = .astgen_failure;1089 ) !std.zig.ErrorBundle.SourceLocationIndex {
9851090 const source = try file.getSource(zcu);
986 // We can only mark children as failed if the ZIR is loaded, which may not1091 const tree = try file.getTree(zcu);
987 // be the case if there were other astgen failures in this file1092 const start = tree.tokenStart(tok);
988 if (file.zir == null) return;1093 const end = start + tree.tokenSlice(tok).len;
9891094 const loc = std.zig.findLineColumn(source.bytes, start);
990 const imports_index = file.zir.?.extra[@intFromEnum(Zir.ExtraIndex.imports)];1095 return eb.addSourceLocation(.{
991 if (imports_index == 0) return;1096 .src_path = try eb.printString("{}", .{file.path.fmt(zcu.comp)}),
992 const extra = file.zir.?.extraData(Zir.Inst.Imports, imports_index);1097 .span_start = start,
9931098 .span_main = start,
994 var extra_index = extra.end;1099 .span_end = @intCast(end),
995 for (0..extra.data.imports_len) |_| {1100 .line = @intCast(loc.line),
996 const item = file.zir.?.extraData(Zir.Inst.Imports.Item, extra_index);1101 .column = @intCast(loc.column),
997 extra_index = item.end;1102 .source_line = try eb.addString(loc.source_line),
9981103 });
999 const import_path = file.zir.?.nullTerminatedString(item.data.name);
1000 if (mem.eql(u8, import_path, "builtin")) continue;
1001
1002 const res = pt.importFile(file, import_path) catch continue;
1003 if (!res.is_pkg and !res.file.multi_pkg) {
1004 res.file.recursiveMarkMultiPkg(pt);
1005 }
1006 }
1007 }1104 }
1008
1009 pub const Index = InternPool.FileIndex;
1010};1105};
10111106
1012/// Represents the contents of a file loaded with `@embedFile`.1107/// Represents the contents of a file loaded with `@embedFile`.
1013pub const EmbedFile = struct {1108pub const EmbedFile = struct {
1014 /// Module that this file is a part of, managed externally.1109 path: Compilation.Path,
1015 owner: *Package.Module,
1016 /// Relative to the owning module's root directory.
1017 sub_file_path: InternPool.NullTerminatedString,
1018
1019 /// `.none` means the file was not loaded, so `stat` is undefined.1110 /// `.none` means the file was not loaded, so `stat` is undefined.
1020 val: InternPool.Index,1111 val: InternPool.Index,
1021 /// If this is `null` and `val` is `.none`, the file has never been loaded.1112 /// If this is `null` and `val` is `.none`, the file has never been loaded.
...@@ -1025,7 +1116,7 @@ pub const EmbedFile = struct {...@@ -1025,7 +1116,7 @@ pub const EmbedFile = struct {
1025 pub const Index = enum(u32) {1116 pub const Index = enum(u32) {
1026 _,1117 _,
1027 pub fn get(idx: Index, zcu: *const Zcu) *EmbedFile {1118 pub fn get(idx: Index, zcu: *const Zcu) *EmbedFile {
1028 return zcu.embed_table.values()[@intFromEnum(idx)];1119 return zcu.embed_table.keys()[@intFromEnum(idx)];
1029 }1120 }
1030 };1121 };
1031};1122};
...@@ -1103,32 +1194,31 @@ pub const SrcLoc = struct {...@@ -1103,32 +1194,31 @@ pub const SrcLoc = struct {
11031194
1104 pub const Span = Ast.Span;1195 pub const Span = Ast.Span;
11051196
1106 pub fn span(src_loc: SrcLoc, gpa: Allocator) !Span {1197 pub fn span(src_loc: SrcLoc, zcu: *const Zcu) !Span {
1107 switch (src_loc.lazy) {1198 switch (src_loc.lazy) {
1108 .unneeded => unreachable,1199 .unneeded => unreachable,
1109 .entire_file => return Span{ .start = 0, .end = 1, .main = 0 },
11101200
1111 .byte_abs => |byte_index| return Span{ .start = byte_index, .end = byte_index + 1, .main = byte_index },1201 .byte_abs => |byte_index| return Span{ .start = byte_index, .end = byte_index + 1, .main = byte_index },
11121202
1113 .token_abs => |tok_index| {1203 .token_abs => |tok_index| {
1114 const tree = try src_loc.file_scope.getTree(gpa);1204 const tree = try src_loc.file_scope.getTree(zcu);
1115 const start = tree.tokenStart(tok_index);1205 const start = tree.tokenStart(tok_index);
1116 const end = start + @as(u32, @intCast(tree.tokenSlice(tok_index).len));1206 const end = start + @as(u32, @intCast(tree.tokenSlice(tok_index).len));
1117 return Span{ .start = start, .end = end, .main = start };1207 return Span{ .start = start, .end = end, .main = start };
1118 },1208 },
1119 .node_abs => |node| {1209 .node_abs => |node| {
1120 const tree = try src_loc.file_scope.getTree(gpa);1210 const tree = try src_loc.file_scope.getTree(zcu);
1121 return tree.nodeToSpan(node);1211 return tree.nodeToSpan(node);
1122 },1212 },
1123 .byte_offset => |byte_off| {1213 .byte_offset => |byte_off| {
1124 const tree = try src_loc.file_scope.getTree(gpa);1214 const tree = try src_loc.file_scope.getTree(zcu);
1125 const tok_index = src_loc.baseSrcToken();1215 const tok_index = src_loc.baseSrcToken();
1126 const start = tree.tokenStart(tok_index) + byte_off;1216 const start = tree.tokenStart(tok_index) + byte_off;
1127 const end = start + @as(u32, @intCast(tree.tokenSlice(tok_index).len));1217 const end = start + @as(u32, @intCast(tree.tokenSlice(tok_index).len));
1128 return Span{ .start = start, .end = end, .main = start };1218 return Span{ .start = start, .end = end, .main = start };
1129 },1219 },
1130 .token_offset => |tok_off| {1220 .token_offset => |tok_off| {
1131 const tree = try src_loc.file_scope.getTree(gpa);1221 const tree = try src_loc.file_scope.getTree(zcu);
1132 const tok_index = tok_off.toAbsolute(src_loc.baseSrcToken());1222 const tok_index = tok_off.toAbsolute(src_loc.baseSrcToken());
1133 const start = tree.tokenStart(tok_index);1223 const start = tree.tokenStart(tok_index);
1134 const end = start + @as(u32, @intCast(tree.tokenSlice(tok_index).len));1224 const end = start + @as(u32, @intCast(tree.tokenSlice(tok_index).len));
...@@ -1136,23 +1226,23 @@ pub const SrcLoc = struct {...@@ -1136,23 +1226,23 @@ pub const SrcLoc = struct {
1136 },1226 },
1137 .node_offset => |traced_off| {1227 .node_offset => |traced_off| {
1138 const node_off = traced_off.x;1228 const node_off = traced_off.x;
1139 const tree = try src_loc.file_scope.getTree(gpa);1229 const tree = try src_loc.file_scope.getTree(zcu);
1140 const node = node_off.toAbsolute(src_loc.base_node);1230 const node = node_off.toAbsolute(src_loc.base_node);
1141 return tree.nodeToSpan(node);1231 return tree.nodeToSpan(node);
1142 },1232 },
1143 .node_offset_main_token => |node_off| {1233 .node_offset_main_token => |node_off| {
1144 const tree = try src_loc.file_scope.getTree(gpa);1234 const tree = try src_loc.file_scope.getTree(zcu);
1145 const node = node_off.toAbsolute(src_loc.base_node);1235 const node = node_off.toAbsolute(src_loc.base_node);
1146 const main_token = tree.nodeMainToken(node);1236 const main_token = tree.nodeMainToken(node);
1147 return tree.tokensToSpan(main_token, main_token, main_token);1237 return tree.tokensToSpan(main_token, main_token, main_token);
1148 },1238 },
1149 .node_offset_bin_op => |node_off| {1239 .node_offset_bin_op => |node_off| {
1150 const tree = try src_loc.file_scope.getTree(gpa);1240 const tree = try src_loc.file_scope.getTree(zcu);
1151 const node = node_off.toAbsolute(src_loc.base_node);1241 const node = node_off.toAbsolute(src_loc.base_node);
1152 return tree.nodeToSpan(node);1242 return tree.nodeToSpan(node);
1153 },1243 },
1154 .node_offset_initializer => |node_off| {1244 .node_offset_initializer => |node_off| {
1155 const tree = try src_loc.file_scope.getTree(gpa);1245 const tree = try src_loc.file_scope.getTree(zcu);
1156 const node = node_off.toAbsolute(src_loc.base_node);1246 const node = node_off.toAbsolute(src_loc.base_node);
1157 return tree.tokensToSpan(1247 return tree.tokensToSpan(
1158 tree.firstToken(node) - 3,1248 tree.firstToken(node) - 3,
...@@ -1161,7 +1251,7 @@ pub const SrcLoc = struct {...@@ -1161,7 +1251,7 @@ pub const SrcLoc = struct {
1161 );1251 );
1162 },1252 },
1163 .node_offset_var_decl_ty => |node_off| {1253 .node_offset_var_decl_ty => |node_off| {
1164 const tree = try src_loc.file_scope.getTree(gpa);1254 const tree = try src_loc.file_scope.getTree(zcu);
1165 const node = node_off.toAbsolute(src_loc.base_node);1255 const node = node_off.toAbsolute(src_loc.base_node);
1166 const full = switch (tree.nodeTag(node)) {1256 const full = switch (tree.nodeTag(node)) {
1167 .global_var_decl,1257 .global_var_decl,
...@@ -1183,7 +1273,7 @@ pub const SrcLoc = struct {...@@ -1183,7 +1273,7 @@ pub const SrcLoc = struct {
1183 return Span{ .start = start, .end = end, .main = start };1273 return Span{ .start = start, .end = end, .main = start };
1184 },1274 },
1185 .node_offset_var_decl_align => |node_off| {1275 .node_offset_var_decl_align => |node_off| {
1186 const tree = try src_loc.file_scope.getTree(gpa);1276 const tree = try src_loc.file_scope.getTree(zcu);
1187 const node = node_off.toAbsolute(src_loc.base_node);1277 const node = node_off.toAbsolute(src_loc.base_node);
1188 var buf: [1]Ast.Node.Index = undefined;1278 var buf: [1]Ast.Node.Index = undefined;
1189 const align_node = if (tree.fullVarDecl(node)) |v|1279 const align_node = if (tree.fullVarDecl(node)) |v|
...@@ -1195,7 +1285,7 @@ pub const SrcLoc = struct {...@@ -1195,7 +1285,7 @@ pub const SrcLoc = struct {
1195 return tree.nodeToSpan(align_node);1285 return tree.nodeToSpan(align_node);
1196 },1286 },
1197 .node_offset_var_decl_section => |node_off| {1287 .node_offset_var_decl_section => |node_off| {
1198 const tree = try src_loc.file_scope.getTree(gpa);1288 const tree = try src_loc.file_scope.getTree(zcu);
1199 const node = node_off.toAbsolute(src_loc.base_node);1289 const node = node_off.toAbsolute(src_loc.base_node);
1200 var buf: [1]Ast.Node.Index = undefined;1290 var buf: [1]Ast.Node.Index = undefined;
1201 const section_node = if (tree.fullVarDecl(node)) |v|1291 const section_node = if (tree.fullVarDecl(node)) |v|
...@@ -1207,7 +1297,7 @@ pub const SrcLoc = struct {...@@ -1207,7 +1297,7 @@ pub const SrcLoc = struct {
1207 return tree.nodeToSpan(section_node);1297 return tree.nodeToSpan(section_node);
1208 },1298 },
1209 .node_offset_var_decl_addrspace => |node_off| {1299 .node_offset_var_decl_addrspace => |node_off| {
1210 const tree = try src_loc.file_scope.getTree(gpa);1300 const tree = try src_loc.file_scope.getTree(zcu);
1211 const node = node_off.toAbsolute(src_loc.base_node);1301 const node = node_off.toAbsolute(src_loc.base_node);
1212 var buf: [1]Ast.Node.Index = undefined;1302 var buf: [1]Ast.Node.Index = undefined;
1213 const addrspace_node = if (tree.fullVarDecl(node)) |v|1303 const addrspace_node = if (tree.fullVarDecl(node)) |v|
...@@ -1219,7 +1309,7 @@ pub const SrcLoc = struct {...@@ -1219,7 +1309,7 @@ pub const SrcLoc = struct {
1219 return tree.nodeToSpan(addrspace_node);1309 return tree.nodeToSpan(addrspace_node);
1220 },1310 },
1221 .node_offset_var_decl_init => |node_off| {1311 .node_offset_var_decl_init => |node_off| {
1222 const tree = try src_loc.file_scope.getTree(gpa);1312 const tree = try src_loc.file_scope.getTree(zcu);
1223 const node = node_off.toAbsolute(src_loc.base_node);1313 const node = node_off.toAbsolute(src_loc.base_node);
1224 const init_node = switch (tree.nodeTag(node)) {1314 const init_node = switch (tree.nodeTag(node)) {
1225 .global_var_decl,1315 .global_var_decl,
...@@ -1233,14 +1323,14 @@ pub const SrcLoc = struct {...@@ -1233,14 +1323,14 @@ pub const SrcLoc = struct {
1233 return tree.nodeToSpan(init_node);1323 return tree.nodeToSpan(init_node);
1234 },1324 },
1235 .node_offset_builtin_call_arg => |builtin_arg| {1325 .node_offset_builtin_call_arg => |builtin_arg| {
1236 const tree = try src_loc.file_scope.getTree(gpa);1326 const tree = try src_loc.file_scope.getTree(zcu);
1237 const node = builtin_arg.builtin_call_node.toAbsolute(src_loc.base_node);1327 const node = builtin_arg.builtin_call_node.toAbsolute(src_loc.base_node);
1238 var buf: [2]Ast.Node.Index = undefined;1328 var buf: [2]Ast.Node.Index = undefined;
1239 const params = tree.builtinCallParams(&buf, node).?;1329 const params = tree.builtinCallParams(&buf, node).?;
1240 return tree.nodeToSpan(params[builtin_arg.arg_index]);1330 return tree.nodeToSpan(params[builtin_arg.arg_index]);
1241 },1331 },
1242 .node_offset_ptrcast_operand => |node_off| {1332 .node_offset_ptrcast_operand => |node_off| {
1243 const tree = try src_loc.file_scope.getTree(gpa);1333 const tree = try src_loc.file_scope.getTree(zcu);
12441334
1245 var node = node_off.toAbsolute(src_loc.base_node);1335 var node = node_off.toAbsolute(src_loc.base_node);
1246 while (true) {1336 while (true) {
...@@ -1273,7 +1363,7 @@ pub const SrcLoc = struct {...@@ -1273,7 +1363,7 @@ pub const SrcLoc = struct {
1273 return tree.nodeToSpan(node);1363 return tree.nodeToSpan(node);
1274 },1364 },
1275 .node_offset_array_access_index => |node_off| {1365 .node_offset_array_access_index => |node_off| {
1276 const tree = try src_loc.file_scope.getTree(gpa);1366 const tree = try src_loc.file_scope.getTree(zcu);
1277 const node = node_off.toAbsolute(src_loc.base_node);1367 const node = node_off.toAbsolute(src_loc.base_node);
1278 return tree.nodeToSpan(tree.nodeData(node).node_and_node[1]);1368 return tree.nodeToSpan(tree.nodeData(node).node_and_node[1]);
1279 },1369 },
...@@ -1282,7 +1372,7 @@ pub const SrcLoc = struct {...@@ -1282,7 +1372,7 @@ pub const SrcLoc = struct {
1282 .node_offset_slice_end,1372 .node_offset_slice_end,
1283 .node_offset_slice_sentinel,1373 .node_offset_slice_sentinel,
1284 => |node_off| {1374 => |node_off| {
1285 const tree = try src_loc.file_scope.getTree(gpa);1375 const tree = try src_loc.file_scope.getTree(zcu);
1286 const node = node_off.toAbsolute(src_loc.base_node);1376 const node = node_off.toAbsolute(src_loc.base_node);
1287 const full = tree.fullSlice(node).?;1377 const full = tree.fullSlice(node).?;
1288 const part_node = switch (src_loc.lazy) {1378 const part_node = switch (src_loc.lazy) {
...@@ -1295,14 +1385,14 @@ pub const SrcLoc = struct {...@@ -1295,14 +1385,14 @@ pub const SrcLoc = struct {
1295 return tree.nodeToSpan(part_node);1385 return tree.nodeToSpan(part_node);
1296 },1386 },
1297 .node_offset_call_func => |node_off| {1387 .node_offset_call_func => |node_off| {
1298 const tree = try src_loc.file_scope.getTree(gpa);1388 const tree = try src_loc.file_scope.getTree(zcu);
1299 const node = node_off.toAbsolute(src_loc.base_node);1389 const node = node_off.toAbsolute(src_loc.base_node);
1300 var buf: [1]Ast.Node.Index = undefined;1390 var buf: [1]Ast.Node.Index = undefined;
1301 const full = tree.fullCall(&buf, node).?;1391 const full = tree.fullCall(&buf, node).?;
1302 return tree.nodeToSpan(full.ast.fn_expr);1392 return tree.nodeToSpan(full.ast.fn_expr);
1303 },1393 },
1304 .node_offset_field_name => |node_off| {1394 .node_offset_field_name => |node_off| {
1305 const tree = try src_loc.file_scope.getTree(gpa);1395 const tree = try src_loc.file_scope.getTree(zcu);
1306 const node = node_off.toAbsolute(src_loc.base_node);1396 const node = node_off.toAbsolute(src_loc.base_node);
1307 var buf: [1]Ast.Node.Index = undefined;1397 var buf: [1]Ast.Node.Index = undefined;
1308 const tok_index = switch (tree.nodeTag(node)) {1398 const tok_index = switch (tree.nodeTag(node)) {
...@@ -1326,7 +1416,7 @@ pub const SrcLoc = struct {...@@ -1326,7 +1416,7 @@ pub const SrcLoc = struct {
1326 return Span{ .start = start, .end = end, .main = start };1416 return Span{ .start = start, .end = end, .main = start };
1327 },1417 },
1328 .node_offset_field_name_init => |node_off| {1418 .node_offset_field_name_init => |node_off| {
1329 const tree = try src_loc.file_scope.getTree(gpa);1419 const tree = try src_loc.file_scope.getTree(zcu);
1330 const node = node_off.toAbsolute(src_loc.base_node);1420 const node = node_off.toAbsolute(src_loc.base_node);
1331 const tok_index = tree.firstToken(node) - 2;1421 const tok_index = tree.firstToken(node) - 2;
1332 const start = tree.tokenStart(tok_index);1422 const start = tree.tokenStart(tok_index);
...@@ -1334,18 +1424,18 @@ pub const SrcLoc = struct {...@@ -1334,18 +1424,18 @@ pub const SrcLoc = struct {
1334 return Span{ .start = start, .end = end, .main = start };1424 return Span{ .start = start, .end = end, .main = start };
1335 },1425 },
1336 .node_offset_deref_ptr => |node_off| {1426 .node_offset_deref_ptr => |node_off| {
1337 const tree = try src_loc.file_scope.getTree(gpa);1427 const tree = try src_loc.file_scope.getTree(zcu);
1338 const node = node_off.toAbsolute(src_loc.base_node);1428 const node = node_off.toAbsolute(src_loc.base_node);
1339 return tree.nodeToSpan(node);1429 return tree.nodeToSpan(node);
1340 },1430 },
1341 .node_offset_asm_source => |node_off| {1431 .node_offset_asm_source => |node_off| {
1342 const tree = try src_loc.file_scope.getTree(gpa);1432 const tree = try src_loc.file_scope.getTree(zcu);
1343 const node = node_off.toAbsolute(src_loc.base_node);1433 const node = node_off.toAbsolute(src_loc.base_node);
1344 const full = tree.fullAsm(node).?;1434 const full = tree.fullAsm(node).?;
1345 return tree.nodeToSpan(full.ast.template);1435 return tree.nodeToSpan(full.ast.template);
1346 },1436 },
1347 .node_offset_asm_ret_ty => |node_off| {1437 .node_offset_asm_ret_ty => |node_off| {
1348 const tree = try src_loc.file_scope.getTree(gpa);1438 const tree = try src_loc.file_scope.getTree(zcu);
1349 const node = node_off.toAbsolute(src_loc.base_node);1439 const node = node_off.toAbsolute(src_loc.base_node);
1350 const full = tree.fullAsm(node).?;1440 const full = tree.fullAsm(node).?;
1351 const asm_output = full.outputs[0];1441 const asm_output = full.outputs[0];
...@@ -1353,7 +1443,7 @@ pub const SrcLoc = struct {...@@ -1353,7 +1443,7 @@ pub const SrcLoc = struct {
1353 },1443 },
13541444
1355 .node_offset_if_cond => |node_off| {1445 .node_offset_if_cond => |node_off| {
1356 const tree = try src_loc.file_scope.getTree(gpa);1446 const tree = try src_loc.file_scope.getTree(zcu);
1357 const node = node_off.toAbsolute(src_loc.base_node);1447 const node = node_off.toAbsolute(src_loc.base_node);
1358 const src_node = switch (tree.nodeTag(node)) {1448 const src_node = switch (tree.nodeTag(node)) {
1359 .if_simple,1449 .if_simple,
...@@ -1381,14 +1471,14 @@ pub const SrcLoc = struct {...@@ -1381,14 +1471,14 @@ pub const SrcLoc = struct {
1381 return tree.nodeToSpan(src_node);1471 return tree.nodeToSpan(src_node);
1382 },1472 },
1383 .for_input => |for_input| {1473 .for_input => |for_input| {
1384 const tree = try src_loc.file_scope.getTree(gpa);1474 const tree = try src_loc.file_scope.getTree(zcu);
1385 const node = for_input.for_node_offset.toAbsolute(src_loc.base_node);1475 const node = for_input.for_node_offset.toAbsolute(src_loc.base_node);
1386 const for_full = tree.fullFor(node).?;1476 const for_full = tree.fullFor(node).?;
1387 const src_node = for_full.ast.inputs[for_input.input_index];1477 const src_node = for_full.ast.inputs[for_input.input_index];
1388 return tree.nodeToSpan(src_node);1478 return tree.nodeToSpan(src_node);
1389 },1479 },
1390 .for_capture_from_input => |node_off| {1480 .for_capture_from_input => |node_off| {
1391 const tree = try src_loc.file_scope.getTree(gpa);1481 const tree = try src_loc.file_scope.getTree(zcu);
1392 const input_node = node_off.toAbsolute(src_loc.base_node);1482 const input_node = node_off.toAbsolute(src_loc.base_node);
1393 // We have to actually linear scan the whole AST to find the for loop1483 // We have to actually linear scan the whole AST to find the for loop
1394 // that contains this input.1484 // that contains this input.
...@@ -1429,7 +1519,7 @@ pub const SrcLoc = struct {...@@ -1429,7 +1519,7 @@ pub const SrcLoc = struct {
1429 } else unreachable;1519 } else unreachable;
1430 },1520 },
1431 .call_arg => |call_arg| {1521 .call_arg => |call_arg| {
1432 const tree = try src_loc.file_scope.getTree(gpa);1522 const tree = try src_loc.file_scope.getTree(zcu);
1433 const node = call_arg.call_node_offset.toAbsolute(src_loc.base_node);1523 const node = call_arg.call_node_offset.toAbsolute(src_loc.base_node);
1434 var buf: [2]Ast.Node.Index = undefined;1524 var buf: [2]Ast.Node.Index = undefined;
1435 const call_full = tree.fullCall(buf[0..1], node) orelse {1525 const call_full = tree.fullCall(buf[0..1], node) orelse {
...@@ -1466,7 +1556,7 @@ pub const SrcLoc = struct {...@@ -1466,7 +1556,7 @@ pub const SrcLoc = struct {
1466 return tree.nodeToSpan(call_full.ast.params[call_arg.arg_index]);1556 return tree.nodeToSpan(call_full.ast.params[call_arg.arg_index]);
1467 },1557 },
1468 .fn_proto_param, .fn_proto_param_type => |fn_proto_param| {1558 .fn_proto_param, .fn_proto_param_type => |fn_proto_param| {
1469 const tree = try src_loc.file_scope.getTree(gpa);1559 const tree = try src_loc.file_scope.getTree(zcu);
1470 const node = fn_proto_param.fn_proto_node_offset.toAbsolute(src_loc.base_node);1560 const node = fn_proto_param.fn_proto_node_offset.toAbsolute(src_loc.base_node);
1471 var buf: [1]Ast.Node.Index = undefined;1561 var buf: [1]Ast.Node.Index = undefined;
1472 const full = tree.fullFnProto(&buf, node).?;1562 const full = tree.fullFnProto(&buf, node).?;
...@@ -1494,17 +1584,17 @@ pub const SrcLoc = struct {...@@ -1494,17 +1584,17 @@ pub const SrcLoc = struct {
1494 unreachable;1584 unreachable;
1495 },1585 },
1496 .node_offset_bin_lhs => |node_off| {1586 .node_offset_bin_lhs => |node_off| {
1497 const tree = try src_loc.file_scope.getTree(gpa);1587 const tree = try src_loc.file_scope.getTree(zcu);
1498 const node = node_off.toAbsolute(src_loc.base_node);1588 const node = node_off.toAbsolute(src_loc.base_node);
1499 return tree.nodeToSpan(tree.nodeData(node).node_and_node[0]);1589 return tree.nodeToSpan(tree.nodeData(node).node_and_node[0]);
1500 },1590 },
1501 .node_offset_bin_rhs => |node_off| {1591 .node_offset_bin_rhs => |node_off| {
1502 const tree = try src_loc.file_scope.getTree(gpa);1592 const tree = try src_loc.file_scope.getTree(zcu);
1503 const node = node_off.toAbsolute(src_loc.base_node);1593 const node = node_off.toAbsolute(src_loc.base_node);
1504 return tree.nodeToSpan(tree.nodeData(node).node_and_node[1]);1594 return tree.nodeToSpan(tree.nodeData(node).node_and_node[1]);
1505 },1595 },
1506 .array_cat_lhs, .array_cat_rhs => |cat| {1596 .array_cat_lhs, .array_cat_rhs => |cat| {
1507 const tree = try src_loc.file_scope.getTree(gpa);1597 const tree = try src_loc.file_scope.getTree(zcu);
1508 const node = cat.array_cat_offset.toAbsolute(src_loc.base_node);1598 const node = cat.array_cat_offset.toAbsolute(src_loc.base_node);
1509 const arr_node = if (src_loc.lazy == .array_cat_lhs)1599 const arr_node = if (src_loc.lazy == .array_cat_lhs)
1510 tree.nodeData(node).node_and_node[0]1600 tree.nodeData(node).node_and_node[0]
...@@ -1530,20 +1620,20 @@ pub const SrcLoc = struct {...@@ -1530,20 +1620,20 @@ pub const SrcLoc = struct {
1530 },1620 },
15311621
1532 .node_offset_try_operand => |node_off| {1622 .node_offset_try_operand => |node_off| {
1533 const tree = try src_loc.file_scope.getTree(gpa);1623 const tree = try src_loc.file_scope.getTree(zcu);
1534 const node = node_off.toAbsolute(src_loc.base_node);1624 const node = node_off.toAbsolute(src_loc.base_node);
1535 return tree.nodeToSpan(tree.nodeData(node).node);1625 return tree.nodeToSpan(tree.nodeData(node).node);
1536 },1626 },
15371627
1538 .node_offset_switch_operand => |node_off| {1628 .node_offset_switch_operand => |node_off| {
1539 const tree = try src_loc.file_scope.getTree(gpa);1629 const tree = try src_loc.file_scope.getTree(zcu);
1540 const node = node_off.toAbsolute(src_loc.base_node);1630 const node = node_off.toAbsolute(src_loc.base_node);
1541 const condition, _ = tree.nodeData(node).node_and_extra;1631 const condition, _ = tree.nodeData(node).node_and_extra;
1542 return tree.nodeToSpan(condition);1632 return tree.nodeToSpan(condition);
1543 },1633 },
15441634
1545 .node_offset_switch_special_prong => |node_off| {1635 .node_offset_switch_special_prong => |node_off| {
1546 const tree = try src_loc.file_scope.getTree(gpa);1636 const tree = try src_loc.file_scope.getTree(zcu);
1547 const switch_node = node_off.toAbsolute(src_loc.base_node);1637 const switch_node = node_off.toAbsolute(src_loc.base_node);
1548 _, const extra_index = tree.nodeData(switch_node).node_and_extra;1638 _, const extra_index = tree.nodeData(switch_node).node_and_extra;
1549 const case_nodes = tree.extraDataSlice(tree.extraData(extra_index, Ast.Node.SubRange), Ast.Node.Index);1639 const case_nodes = tree.extraDataSlice(tree.extraData(extra_index, Ast.Node.SubRange), Ast.Node.Index);
...@@ -1560,7 +1650,7 @@ pub const SrcLoc = struct {...@@ -1560,7 +1650,7 @@ pub const SrcLoc = struct {
1560 },1650 },
15611651
1562 .node_offset_switch_range => |node_off| {1652 .node_offset_switch_range => |node_off| {
1563 const tree = try src_loc.file_scope.getTree(gpa);1653 const tree = try src_loc.file_scope.getTree(zcu);
1564 const switch_node = node_off.toAbsolute(src_loc.base_node);1654 const switch_node = node_off.toAbsolute(src_loc.base_node);
1565 _, const extra_index = tree.nodeData(switch_node).node_and_extra;1655 _, const extra_index = tree.nodeData(switch_node).node_and_extra;
1566 const case_nodes = tree.extraDataSlice(tree.extraData(extra_index, Ast.Node.SubRange), Ast.Node.Index);1656 const case_nodes = tree.extraDataSlice(tree.extraData(extra_index, Ast.Node.SubRange), Ast.Node.Index);
...@@ -1580,28 +1670,28 @@ pub const SrcLoc = struct {...@@ -1580,28 +1670,28 @@ pub const SrcLoc = struct {
1580 } else unreachable;1670 } else unreachable;
1581 },1671 },
1582 .node_offset_fn_type_align => |node_off| {1672 .node_offset_fn_type_align => |node_off| {
1583 const tree = try src_loc.file_scope.getTree(gpa);1673 const tree = try src_loc.file_scope.getTree(zcu);
1584 const node = node_off.toAbsolute(src_loc.base_node);1674 const node = node_off.toAbsolute(src_loc.base_node);
1585 var buf: [1]Ast.Node.Index = undefined;1675 var buf: [1]Ast.Node.Index = undefined;
1586 const full = tree.fullFnProto(&buf, node).?;1676 const full = tree.fullFnProto(&buf, node).?;
1587 return tree.nodeToSpan(full.ast.align_expr.unwrap().?);1677 return tree.nodeToSpan(full.ast.align_expr.unwrap().?);
1588 },1678 },
1589 .node_offset_fn_type_addrspace => |node_off| {1679 .node_offset_fn_type_addrspace => |node_off| {
1590 const tree = try src_loc.file_scope.getTree(gpa);1680 const tree = try src_loc.file_scope.getTree(zcu);
1591 const node = node_off.toAbsolute(src_loc.base_node);1681 const node = node_off.toAbsolute(src_loc.base_node);
1592 var buf: [1]Ast.Node.Index = undefined;1682 var buf: [1]Ast.Node.Index = undefined;
1593 const full = tree.fullFnProto(&buf, node).?;1683 const full = tree.fullFnProto(&buf, node).?;
1594 return tree.nodeToSpan(full.ast.addrspace_expr.unwrap().?);1684 return tree.nodeToSpan(full.ast.addrspace_expr.unwrap().?);
1595 },1685 },
1596 .node_offset_fn_type_section => |node_off| {1686 .node_offset_fn_type_section => |node_off| {
1597 const tree = try src_loc.file_scope.getTree(gpa);1687 const tree = try src_loc.file_scope.getTree(zcu);
1598 const node = node_off.toAbsolute(src_loc.base_node);1688 const node = node_off.toAbsolute(src_loc.base_node);
1599 var buf: [1]Ast.Node.Index = undefined;1689 var buf: [1]Ast.Node.Index = undefined;
1600 const full = tree.fullFnProto(&buf, node).?;1690 const full = tree.fullFnProto(&buf, node).?;
1601 return tree.nodeToSpan(full.ast.section_expr.unwrap().?);1691 return tree.nodeToSpan(full.ast.section_expr.unwrap().?);
1602 },1692 },
1603 .node_offset_fn_type_cc => |node_off| {1693 .node_offset_fn_type_cc => |node_off| {
1604 const tree = try src_loc.file_scope.getTree(gpa);1694 const tree = try src_loc.file_scope.getTree(zcu);
1605 const node = node_off.toAbsolute(src_loc.base_node);1695 const node = node_off.toAbsolute(src_loc.base_node);
1606 var buf: [1]Ast.Node.Index = undefined;1696 var buf: [1]Ast.Node.Index = undefined;
1607 const full = tree.fullFnProto(&buf, node).?;1697 const full = tree.fullFnProto(&buf, node).?;
...@@ -1609,14 +1699,14 @@ pub const SrcLoc = struct {...@@ -1609,14 +1699,14 @@ pub const SrcLoc = struct {
1609 },1699 },
16101700
1611 .node_offset_fn_type_ret_ty => |node_off| {1701 .node_offset_fn_type_ret_ty => |node_off| {
1612 const tree = try src_loc.file_scope.getTree(gpa);1702 const tree = try src_loc.file_scope.getTree(zcu);
1613 const node = node_off.toAbsolute(src_loc.base_node);1703 const node = node_off.toAbsolute(src_loc.base_node);
1614 var buf: [1]Ast.Node.Index = undefined;1704 var buf: [1]Ast.Node.Index = undefined;
1615 const full = tree.fullFnProto(&buf, node).?;1705 const full = tree.fullFnProto(&buf, node).?;
1616 return tree.nodeToSpan(full.ast.return_type.unwrap().?);1706 return tree.nodeToSpan(full.ast.return_type.unwrap().?);
1617 },1707 },
1618 .node_offset_param => |node_off| {1708 .node_offset_param => |node_off| {
1619 const tree = try src_loc.file_scope.getTree(gpa);1709 const tree = try src_loc.file_scope.getTree(zcu);
1620 const node = node_off.toAbsolute(src_loc.base_node);1710 const node = node_off.toAbsolute(src_loc.base_node);
16211711
1622 var first_tok = tree.firstToken(node);1712 var first_tok = tree.firstToken(node);
...@@ -1631,7 +1721,7 @@ pub const SrcLoc = struct {...@@ -1631,7 +1721,7 @@ pub const SrcLoc = struct {
1631 );1721 );
1632 },1722 },
1633 .token_offset_param => |token_off| {1723 .token_offset_param => |token_off| {
1634 const tree = try src_loc.file_scope.getTree(gpa);1724 const tree = try src_loc.file_scope.getTree(zcu);
1635 const main_token = tree.nodeMainToken(src_loc.base_node);1725 const main_token = tree.nodeMainToken(src_loc.base_node);
1636 const tok_index = token_off.toAbsolute(main_token);1726 const tok_index = token_off.toAbsolute(main_token);
16371727
...@@ -1648,14 +1738,14 @@ pub const SrcLoc = struct {...@@ -1648,14 +1738,14 @@ pub const SrcLoc = struct {
1648 },1738 },
16491739
1650 .node_offset_anyframe_type => |node_off| {1740 .node_offset_anyframe_type => |node_off| {
1651 const tree = try src_loc.file_scope.getTree(gpa);1741 const tree = try src_loc.file_scope.getTree(zcu);
1652 const parent_node = node_off.toAbsolute(src_loc.base_node);1742 const parent_node = node_off.toAbsolute(src_loc.base_node);
1653 _, const child_type = tree.nodeData(parent_node).token_and_node;1743 _, const child_type = tree.nodeData(parent_node).token_and_node;
1654 return tree.nodeToSpan(child_type);1744 return tree.nodeToSpan(child_type);
1655 },1745 },
16561746
1657 .node_offset_lib_name => |node_off| {1747 .node_offset_lib_name => |node_off| {
1658 const tree = try src_loc.file_scope.getTree(gpa);1748 const tree = try src_loc.file_scope.getTree(zcu);
1659 const parent_node = node_off.toAbsolute(src_loc.base_node);1749 const parent_node = node_off.toAbsolute(src_loc.base_node);
1660 var buf: [1]Ast.Node.Index = undefined;1750 var buf: [1]Ast.Node.Index = undefined;
1661 const full = tree.fullFnProto(&buf, parent_node).?;1751 const full = tree.fullFnProto(&buf, parent_node).?;
...@@ -1666,75 +1756,75 @@ pub const SrcLoc = struct {...@@ -1666,75 +1756,75 @@ pub const SrcLoc = struct {
1666 },1756 },
16671757
1668 .node_offset_array_type_len => |node_off| {1758 .node_offset_array_type_len => |node_off| {
1669 const tree = try src_loc.file_scope.getTree(gpa);1759 const tree = try src_loc.file_scope.getTree(zcu);
1670 const parent_node = node_off.toAbsolute(src_loc.base_node);1760 const parent_node = node_off.toAbsolute(src_loc.base_node);
16711761
1672 const full = tree.fullArrayType(parent_node).?;1762 const full = tree.fullArrayType(parent_node).?;
1673 return tree.nodeToSpan(full.ast.elem_count);1763 return tree.nodeToSpan(full.ast.elem_count);
1674 },1764 },
1675 .node_offset_array_type_sentinel => |node_off| {1765 .node_offset_array_type_sentinel => |node_off| {
1676 const tree = try src_loc.file_scope.getTree(gpa);1766 const tree = try src_loc.file_scope.getTree(zcu);
1677 const parent_node = node_off.toAbsolute(src_loc.base_node);1767 const parent_node = node_off.toAbsolute(src_loc.base_node);
16781768
1679 const full = tree.fullArrayType(parent_node).?;1769 const full = tree.fullArrayType(parent_node).?;
1680 return tree.nodeToSpan(full.ast.sentinel.unwrap().?);1770 return tree.nodeToSpan(full.ast.sentinel.unwrap().?);
1681 },1771 },
1682 .node_offset_array_type_elem => |node_off| {1772 .node_offset_array_type_elem => |node_off| {
1683 const tree = try src_loc.file_scope.getTree(gpa);1773 const tree = try src_loc.file_scope.getTree(zcu);
1684 const parent_node = node_off.toAbsolute(src_loc.base_node);1774 const parent_node = node_off.toAbsolute(src_loc.base_node);
16851775
1686 const full = tree.fullArrayType(parent_node).?;1776 const full = tree.fullArrayType(parent_node).?;
1687 return tree.nodeToSpan(full.ast.elem_type);1777 return tree.nodeToSpan(full.ast.elem_type);
1688 },1778 },
1689 .node_offset_un_op => |node_off| {1779 .node_offset_un_op => |node_off| {
1690 const tree = try src_loc.file_scope.getTree(gpa);1780 const tree = try src_loc.file_scope.getTree(zcu);
1691 const node = node_off.toAbsolute(src_loc.base_node);1781 const node = node_off.toAbsolute(src_loc.base_node);
1692 return tree.nodeToSpan(tree.nodeData(node).node);1782 return tree.nodeToSpan(tree.nodeData(node).node);
1693 },1783 },
1694 .node_offset_ptr_elem => |node_off| {1784 .node_offset_ptr_elem => |node_off| {
1695 const tree = try src_loc.file_scope.getTree(gpa);1785 const tree = try src_loc.file_scope.getTree(zcu);
1696 const parent_node = node_off.toAbsolute(src_loc.base_node);1786 const parent_node = node_off.toAbsolute(src_loc.base_node);
16971787
1698 const full = tree.fullPtrType(parent_node).?;1788 const full = tree.fullPtrType(parent_node).?;
1699 return tree.nodeToSpan(full.ast.child_type);1789 return tree.nodeToSpan(full.ast.child_type);
1700 },1790 },
1701 .node_offset_ptr_sentinel => |node_off| {1791 .node_offset_ptr_sentinel => |node_off| {
1702 const tree = try src_loc.file_scope.getTree(gpa);1792 const tree = try src_loc.file_scope.getTree(zcu);
1703 const parent_node = node_off.toAbsolute(src_loc.base_node);1793 const parent_node = node_off.toAbsolute(src_loc.base_node);
17041794
1705 const full = tree.fullPtrType(parent_node).?;1795 const full = tree.fullPtrType(parent_node).?;
1706 return tree.nodeToSpan(full.ast.sentinel.unwrap().?);1796 return tree.nodeToSpan(full.ast.sentinel.unwrap().?);
1707 },1797 },
1708 .node_offset_ptr_align => |node_off| {1798 .node_offset_ptr_align => |node_off| {
1709 const tree = try src_loc.file_scope.getTree(gpa);1799 const tree = try src_loc.file_scope.getTree(zcu);
1710 const parent_node = node_off.toAbsolute(src_loc.base_node);1800 const parent_node = node_off.toAbsolute(src_loc.base_node);
17111801
1712 const full = tree.fullPtrType(parent_node).?;1802 const full = tree.fullPtrType(parent_node).?;
1713 return tree.nodeToSpan(full.ast.align_node.unwrap().?);1803 return tree.nodeToSpan(full.ast.align_node.unwrap().?);
1714 },1804 },
1715 .node_offset_ptr_addrspace => |node_off| {1805 .node_offset_ptr_addrspace => |node_off| {
1716 const tree = try src_loc.file_scope.getTree(gpa);1806 const tree = try src_loc.file_scope.getTree(zcu);
1717 const parent_node = node_off.toAbsolute(src_loc.base_node);1807 const parent_node = node_off.toAbsolute(src_loc.base_node);
17181808
1719 const full = tree.fullPtrType(parent_node).?;1809 const full = tree.fullPtrType(parent_node).?;
1720 return tree.nodeToSpan(full.ast.addrspace_node.unwrap().?);1810 return tree.nodeToSpan(full.ast.addrspace_node.unwrap().?);
1721 },1811 },
1722 .node_offset_ptr_bitoffset => |node_off| {1812 .node_offset_ptr_bitoffset => |node_off| {
1723 const tree = try src_loc.file_scope.getTree(gpa);1813 const tree = try src_loc.file_scope.getTree(zcu);
1724 const parent_node = node_off.toAbsolute(src_loc.base_node);1814 const parent_node = node_off.toAbsolute(src_loc.base_node);
17251815
1726 const full = tree.fullPtrType(parent_node).?;1816 const full = tree.fullPtrType(parent_node).?;
1727 return tree.nodeToSpan(full.ast.bit_range_start.unwrap().?);1817 return tree.nodeToSpan(full.ast.bit_range_start.unwrap().?);
1728 },1818 },
1729 .node_offset_ptr_hostsize => |node_off| {1819 .node_offset_ptr_hostsize => |node_off| {
1730 const tree = try src_loc.file_scope.getTree(gpa);1820 const tree = try src_loc.file_scope.getTree(zcu);
1731 const parent_node = node_off.toAbsolute(src_loc.base_node);1821 const parent_node = node_off.toAbsolute(src_loc.base_node);
17321822
1733 const full = tree.fullPtrType(parent_node).?;1823 const full = tree.fullPtrType(parent_node).?;
1734 return tree.nodeToSpan(full.ast.bit_range_end.unwrap().?);1824 return tree.nodeToSpan(full.ast.bit_range_end.unwrap().?);
1735 },1825 },
1736 .node_offset_container_tag => |node_off| {1826 .node_offset_container_tag => |node_off| {
1737 const tree = try src_loc.file_scope.getTree(gpa);1827 const tree = try src_loc.file_scope.getTree(zcu);
1738 const parent_node = node_off.toAbsolute(src_loc.base_node);1828 const parent_node = node_off.toAbsolute(src_loc.base_node);
17391829
1740 switch (tree.nodeTag(parent_node)) {1830 switch (tree.nodeTag(parent_node)) {
...@@ -1757,7 +1847,7 @@ pub const SrcLoc = struct {...@@ -1757,7 +1847,7 @@ pub const SrcLoc = struct {
1757 }1847 }
1758 },1848 },
1759 .node_offset_field_default => |node_off| {1849 .node_offset_field_default => |node_off| {
1760 const tree = try src_loc.file_scope.getTree(gpa);1850 const tree = try src_loc.file_scope.getTree(zcu);
1761 const parent_node = node_off.toAbsolute(src_loc.base_node);1851 const parent_node = node_off.toAbsolute(src_loc.base_node);
17621852
1763 const full: Ast.full.ContainerField = switch (tree.nodeTag(parent_node)) {1853 const full: Ast.full.ContainerField = switch (tree.nodeTag(parent_node)) {
...@@ -1768,7 +1858,7 @@ pub const SrcLoc = struct {...@@ -1768,7 +1858,7 @@ pub const SrcLoc = struct {
1768 return tree.nodeToSpan(full.ast.value_expr.unwrap().?);1858 return tree.nodeToSpan(full.ast.value_expr.unwrap().?);
1769 },1859 },
1770 .node_offset_init_ty => |node_off| {1860 .node_offset_init_ty => |node_off| {
1771 const tree = try src_loc.file_scope.getTree(gpa);1861 const tree = try src_loc.file_scope.getTree(zcu);
1772 const parent_node = node_off.toAbsolute(src_loc.base_node);1862 const parent_node = node_off.toAbsolute(src_loc.base_node);
17731863
1774 var buf: [2]Ast.Node.Index = undefined;1864 var buf: [2]Ast.Node.Index = undefined;
...@@ -1779,7 +1869,7 @@ pub const SrcLoc = struct {...@@ -1779,7 +1869,7 @@ pub const SrcLoc = struct {
1779 return tree.nodeToSpan(type_expr);1869 return tree.nodeToSpan(type_expr);
1780 },1870 },
1781 .node_offset_store_ptr => |node_off| {1871 .node_offset_store_ptr => |node_off| {
1782 const tree = try src_loc.file_scope.getTree(gpa);1872 const tree = try src_loc.file_scope.getTree(zcu);
1783 const node = node_off.toAbsolute(src_loc.base_node);1873 const node = node_off.toAbsolute(src_loc.base_node);
17841874
1785 switch (tree.nodeTag(node)) {1875 switch (tree.nodeTag(node)) {
...@@ -1806,7 +1896,7 @@ pub const SrcLoc = struct {...@@ -1806,7 +1896,7 @@ pub const SrcLoc = struct {
1806 }1896 }
1807 },1897 },
1808 .node_offset_store_operand => |node_off| {1898 .node_offset_store_operand => |node_off| {
1809 const tree = try src_loc.file_scope.getTree(gpa);1899 const tree = try src_loc.file_scope.getTree(zcu);
1810 const node = node_off.toAbsolute(src_loc.base_node);1900 const node = node_off.toAbsolute(src_loc.base_node);
18111901
1812 switch (tree.nodeTag(node)) {1902 switch (tree.nodeTag(node)) {
...@@ -1833,7 +1923,7 @@ pub const SrcLoc = struct {...@@ -1833,7 +1923,7 @@ pub const SrcLoc = struct {
1833 }1923 }
1834 },1924 },
1835 .node_offset_return_operand => |node_off| {1925 .node_offset_return_operand => |node_off| {
1836 const tree = try src_loc.file_scope.getTree(gpa);1926 const tree = try src_loc.file_scope.getTree(zcu);
1837 const node = node_off.toAbsolute(src_loc.base_node);1927 const node = node_off.toAbsolute(src_loc.base_node);
1838 if (tree.nodeTag(node) == .@"return") {1928 if (tree.nodeTag(node) == .@"return") {
1839 if (tree.nodeData(node).opt_node.unwrap()) |lhs| {1929 if (tree.nodeData(node).opt_node.unwrap()) |lhs| {
...@@ -1847,7 +1937,7 @@ pub const SrcLoc = struct {...@@ -1847,7 +1937,7 @@ pub const SrcLoc = struct {
1847 .container_field_type,1937 .container_field_type,
1848 .container_field_align,1938 .container_field_align,
1849 => |field_idx| {1939 => |field_idx| {
1850 const tree = try src_loc.file_scope.getTree(gpa);1940 const tree = try src_loc.file_scope.getTree(zcu);
1851 const node = src_loc.base_node;1941 const node = src_loc.base_node;
1852 var buf: [2]Ast.Node.Index = undefined;1942 var buf: [2]Ast.Node.Index = undefined;
1853 const container_decl = tree.fullContainerDecl(&buf, node) orelse1943 const container_decl = tree.fullContainerDecl(&buf, node) orelse
...@@ -1875,7 +1965,7 @@ pub const SrcLoc = struct {...@@ -1875,7 +1965,7 @@ pub const SrcLoc = struct {
1875 } else unreachable;1965 } else unreachable;
1876 },1966 },
1877 .tuple_field_type, .tuple_field_init => |field_info| {1967 .tuple_field_type, .tuple_field_init => |field_info| {
1878 const tree = try src_loc.file_scope.getTree(gpa);1968 const tree = try src_loc.file_scope.getTree(zcu);
1879 const node = src_loc.base_node;1969 const node = src_loc.base_node;
1880 var buf: [2]Ast.Node.Index = undefined;1970 var buf: [2]Ast.Node.Index = undefined;
1881 const container_decl = tree.fullContainerDecl(&buf, node) orelse1971 const container_decl = tree.fullContainerDecl(&buf, node) orelse
...@@ -1889,7 +1979,7 @@ pub const SrcLoc = struct {...@@ -1889,7 +1979,7 @@ pub const SrcLoc = struct {
1889 });1979 });
1890 },1980 },
1891 .init_elem => |init_elem| {1981 .init_elem => |init_elem| {
1892 const tree = try src_loc.file_scope.getTree(gpa);1982 const tree = try src_loc.file_scope.getTree(zcu);
1893 const init_node = init_elem.init_node_offset.toAbsolute(src_loc.base_node);1983 const init_node = init_elem.init_node_offset.toAbsolute(src_loc.base_node);
1894 var buf: [2]Ast.Node.Index = undefined;1984 var buf: [2]Ast.Node.Index = undefined;
1895 if (tree.fullArrayInit(&buf, init_node)) |full| {1985 if (tree.fullArrayInit(&buf, init_node)) |full| {
...@@ -1928,7 +2018,7 @@ pub const SrcLoc = struct {...@@ -1928,7 +2018,7 @@ pub const SrcLoc = struct {
1928 .init_field_dll_import => "dll_import",2018 .init_field_dll_import => "dll_import",
1929 else => unreachable,2019 else => unreachable,
1930 };2020 };
1931 const tree = try src_loc.file_scope.getTree(gpa);2021 const tree = try src_loc.file_scope.getTree(zcu);
1932 const node = builtin_call_node.toAbsolute(src_loc.base_node);2022 const node = builtin_call_node.toAbsolute(src_loc.base_node);
1933 var builtin_buf: [2]Ast.Node.Index = undefined;2023 var builtin_buf: [2]Ast.Node.Index = undefined;
1934 const args = tree.builtinCallParams(&builtin_buf, node).?;2024 const args = tree.builtinCallParams(&builtin_buf, node).?;
...@@ -1967,7 +2057,7 @@ pub const SrcLoc = struct {...@@ -1967,7 +2057,7 @@ pub const SrcLoc = struct {
1967 else => unreachable,2057 else => unreachable,
1968 };2058 };
19692059
1970 const tree = try src_loc.file_scope.getTree(gpa);2060 const tree = try src_loc.file_scope.getTree(zcu);
1971 const switch_node = switch_node_offset.toAbsolute(src_loc.base_node);2061 const switch_node = switch_node_offset.toAbsolute(src_loc.base_node);
1972 _, const extra_index = tree.nodeData(switch_node).node_and_extra;2062 _, const extra_index = tree.nodeData(switch_node).node_and_extra;
1973 const case_nodes = tree.extraDataSlice(tree.extraData(extra_index, Ast.Node.SubRange), Ast.Node.Index);2063 const case_nodes = tree.extraDataSlice(tree.extraData(extra_index, Ast.Node.SubRange), Ast.Node.Index);
...@@ -2062,7 +2152,7 @@ pub const SrcLoc = struct {...@@ -2062,7 +2152,7 @@ pub const SrcLoc = struct {
2062 }2152 }
2063 },2153 },
2064 .func_decl_param_comptime => |param_idx| {2154 .func_decl_param_comptime => |param_idx| {
2065 const tree = try src_loc.file_scope.getTree(gpa);2155 const tree = try src_loc.file_scope.getTree(zcu);
2066 var buf: [1]Ast.Node.Index = undefined;2156 var buf: [1]Ast.Node.Index = undefined;
2067 const full = tree.fullFnProto(&buf, src_loc.base_node).?;2157 const full = tree.fullFnProto(&buf, src_loc.base_node).?;
2068 var param_it = full.iterate(tree);2158 var param_it = full.iterate(tree);
...@@ -2071,7 +2161,7 @@ pub const SrcLoc = struct {...@@ -2071,7 +2161,7 @@ pub const SrcLoc = struct {
2071 return tree.tokenToSpan(param.comptime_noalias.?);2161 return tree.tokenToSpan(param.comptime_noalias.?);
2072 },2162 },
2073 .func_decl_param_ty => |param_idx| {2163 .func_decl_param_ty => |param_idx| {
2074 const tree = try src_loc.file_scope.getTree(gpa);2164 const tree = try src_loc.file_scope.getTree(zcu);
2075 var buf: [1]Ast.Node.Index = undefined;2165 var buf: [1]Ast.Node.Index = undefined;
2076 const full = tree.fullFnProto(&buf, src_loc.base_node).?;2166 const full = tree.fullFnProto(&buf, src_loc.base_node).?;
2077 var param_it = full.iterate(tree);2167 var param_it = full.iterate(tree);
...@@ -2100,9 +2190,6 @@ pub const LazySrcLoc = struct {...@@ -2100,9 +2190,6 @@ pub const LazySrcLoc = struct {
2100 /// value is being set to this tag.2190 /// value is being set to this tag.
2101 /// `base_node_inst` is unused.2191 /// `base_node_inst` is unused.
2102 unneeded,2192 unneeded,
2103 /// Means the source location points to an entire file; not any particular
2104 /// location within the file. `file_scope` union field will be active.
2105 entire_file,
2106 /// The source location points to a byte offset within a source file,2193 /// The source location points to a byte offset within a source file,
2107 /// offset from 0. The source file is determined contextually.2194 /// offset from 0. The source file is determined contextually.
2108 byte_abs: u32,2195 byte_abs: u32,
...@@ -2521,10 +2608,7 @@ pub const LazySrcLoc = struct {...@@ -2521,10 +2608,7 @@ pub const LazySrcLoc = struct {
25212608
2522 /// Like `upgrade`, but returns `null` if the source location has been lost across incremental updates.2609 /// Like `upgrade`, but returns `null` if the source location has been lost across incremental updates.
2523 pub fn upgradeOrLost(lazy: LazySrcLoc, zcu: *Zcu) ?SrcLoc {2610 pub fn upgradeOrLost(lazy: LazySrcLoc, zcu: *Zcu) ?SrcLoc {
2524 const file, const base_node: Ast.Node.Index = if (lazy.offset == .entire_file) .{2611 const file, const base_node: Ast.Node.Index = resolveBaseNode(lazy.base_node_inst, zcu) orelse return null;
2525 zcu.fileByIndex(lazy.base_node_inst.resolveFile(&zcu.intern_pool)),
2526 .root,
2527 } else resolveBaseNode(lazy.base_node_inst, zcu) orelse return null;
2528 return .{2612 return .{
2529 .file_scope = file,2613 .file_scope = file,
2530 .base_node = base_node,2614 .base_node = base_node,
...@@ -2544,15 +2628,16 @@ pub const LazySrcLoc = struct {...@@ -2544,15 +2628,16 @@ pub const LazySrcLoc = struct {
2544 return true;2628 return true;
2545 };2629 };
2546 if (lhs_src.file_scope != rhs_src.file_scope) {2630 if (lhs_src.file_scope != rhs_src.file_scope) {
2547 return std.mem.order(2631 const lhs_path = lhs_src.file_scope.path;
2548 u8,2632 const rhs_path = rhs_src.file_scope.path;
2549 lhs_src.file_scope.sub_file_path,2633 if (lhs_path.root != rhs_path.root) {
2550 rhs_src.file_scope.sub_file_path,2634 return @intFromEnum(lhs_path.root) < @intFromEnum(rhs_path.root);
2551 ).compare(.lt);2635 }
2636 return std.mem.order(u8, lhs_path.sub_path, rhs_path.sub_path).compare(.lt);
2552 }2637 }
25532638
2554 const lhs_span = try lhs_src.span(zcu.gpa);2639 const lhs_span = try lhs_src.span(zcu);
2555 const rhs_span = try rhs_src.span(zcu.gpa);2640 const rhs_span = try rhs_src.span(zcu);
2556 return lhs_span.main < rhs_span.main;2641 return lhs_span.main < rhs_span.main;
2557 }2642 }
2558};2643};
...@@ -2583,16 +2668,16 @@ pub fn deinit(zcu: *Zcu) void {...@@ -2583,16 +2668,16 @@ pub fn deinit(zcu: *Zcu) void {
25832668
2584 if (zcu.llvm_object) |llvm_object| llvm_object.deinit();2669 if (zcu.llvm_object) |llvm_object| llvm_object.deinit();
25852670
2586 for (zcu.import_table.keys()) |key| {2671 zcu.builtin_modules.deinit(gpa);
2587 gpa.free(key);2672 zcu.module_roots.deinit(gpa);
2588 }2673 for (zcu.import_table.keys()) |file_index| {
2589 for (zcu.import_table.values()) |file_index| {
2590 pt.destroyFile(file_index);2674 pt.destroyFile(file_index);
2591 }2675 }
2592 zcu.import_table.deinit(gpa);2676 zcu.import_table.deinit(gpa);
2677 zcu.alive_files.deinit(gpa);
25932678
2594 for (zcu.embed_table.keys(), zcu.embed_table.values()) |path, embed_file| {2679 for (zcu.embed_table.keys()) |embed_file| {
2595 gpa.free(path);2680 embed_file.path.deinit(gpa);
2596 gpa.destroy(embed_file);2681 gpa.destroy(embed_file);
2597 }2682 }
2598 zcu.embed_table.deinit(gpa);2683 zcu.embed_table.deinit(gpa);
...@@ -2610,9 +2695,10 @@ pub fn deinit(zcu: *Zcu) void {...@@ -2610,9 +2695,10 @@ pub fn deinit(zcu: *Zcu) void {
2610 zcu.failed_types.deinit(gpa);2695 zcu.failed_types.deinit(gpa);
26112696
2612 for (zcu.failed_files.values()) |value| {2697 for (zcu.failed_files.values()) |value| {
2613 if (value) |msg| msg.destroy(gpa);2698 if (value) |msg| gpa.free(msg);
2614 }2699 }
2615 zcu.failed_files.deinit(gpa);2700 zcu.failed_files.deinit(gpa);
2701 zcu.failed_imports.deinit(gpa);
26162702
2617 for (zcu.failed_exports.values()) |value| {2703 for (zcu.failed_exports.values()) |value| {
2618 value.destroy(gpa);2704 value.destroy(gpa);
...@@ -3407,27 +3493,21 @@ pub fn ensureNavValAnalysisQueued(zcu: *Zcu, nav_id: InternPool.Nav.Index) !void...@@ -3407,27 +3493,21 @@ pub fn ensureNavValAnalysisQueued(zcu: *Zcu, nav_id: InternPool.Nav.Index) !void
3407 zcu.nav_val_analysis_queued.putAssumeCapacityNoClobber(nav_id, {});3493 zcu.nav_val_analysis_queued.putAssumeCapacityNoClobber(nav_id, {});
3408}3494}
34093495
3410pub const ImportFileResult = struct {3496pub const ImportResult = struct {
3411 file: *File,3497 /// Whether `file` has been newly created; in other words, whether this is the first import of
3412 file_index: File.Index,3498 /// this file. This should only be `true` when importing files during AstGen. After that, all
3499 /// files should have already been discovered.
3413 is_new: bool,3500 is_new: bool,
3414 is_pkg: bool,
3415};
34163501
3417pub fn computePathDigest(zcu: *Zcu, mod: *Package.Module, sub_file_path: []const u8) Cache.BinDigest {3502 /// `file.mod` is not populated by this function, so if `is_new`, then it is `undefined`.
3418 const want_local_cache = mod == zcu.main_mod;3503 file: *Zcu.File,
3419 var path_hash: Cache.HashHelper = .{};3504 file_index: File.Index,
3420 path_hash.addBytes(build_options.version);3505
3421 path_hash.add(builtin.zig_backend);3506 /// If this import was a simple file path, this is `null`; the imported file should exist within
3422 if (!want_local_cache) {3507 /// the importer's module. Otherwise, it's the module which the import resolved to. This module
3423 path_hash.addOptionalBytes(mod.root.root_dir.path);3508 /// could match the module of `cur_file`, since a module can depend on itself.
3424 path_hash.addBytes(mod.root.sub_path);3509 module: ?*Package.Module,
3425 }3510};
3426 path_hash.addBytes(sub_file_path);
3427 var bin: Cache.BinDigest = undefined;
3428 path_hash.hasher.final(&bin);
3429 return bin;
3430}
34313511
3432/// Delete all the Export objects that are caused by this `AnalUnit`. Re-analysis of3512/// Delete all the Export objects that are caused by this `AnalUnit`. Re-analysis of
3433/// this `AnalUnit` will cause them to be re-created (or not).3513/// this `AnalUnit` will cause them to be re-created (or not).
...@@ -3941,15 +4021,7 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv...@@ -3941,15 +4021,7 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv
39414021
3942 try type_queue.ensureTotalCapacity(gpa, zcu.analysis_roots.len);4022 try type_queue.ensureTotalCapacity(gpa, zcu.analysis_roots.len);
3943 for (zcu.analysis_roots.slice()) |mod| {4023 for (zcu.analysis_roots.slice()) |mod| {
3944 // Logic ripped from `Zcu.PerThread.importPkg`.4024 const file = zcu.module_roots.get(mod).?.unwrap() orelse continue;
3945 // TODO: this is silly, `Module` should just store a reference to its root `File`.
3946 const resolved_path = try std.fs.path.resolve(gpa, &.{
3947 mod.root.root_dir.path orelse ".",
3948 mod.root.sub_path,
3949 mod.root_src_path,
3950 });
3951 defer gpa.free(resolved_path);
3952 const file = zcu.import_table.get(resolved_path).?;
3953 const root_ty = zcu.fileRootType(file);4025 const root_ty = zcu.fileRootType(file);
3954 if (root_ty == .none) continue;4026 if (root_ty == .none) continue;
3955 type_queue.putAssumeCapacityNoClobber(root_ty, null);4027 type_queue.putAssumeCapacityNoClobber(root_ty, null);
...@@ -4229,8 +4301,8 @@ fn formatAnalUnit(data: struct { unit: AnalUnit, zcu: *Zcu }, comptime fmt: []co...@@ -4229,8 +4301,8 @@ fn formatAnalUnit(data: struct { unit: AnalUnit, zcu: *Zcu }, comptime fmt: []co
4229 .@"comptime" => |cu_id| {4301 .@"comptime" => |cu_id| {
4230 const cu = ip.getComptimeUnit(cu_id);4302 const cu = ip.getComptimeUnit(cu_id);
4231 if (cu.zir_index.resolveFull(ip)) |resolved| {4303 if (cu.zir_index.resolveFull(ip)) |resolved| {
4232 const file_path = zcu.fileByIndex(resolved.file).sub_file_path;4304 const file_path = zcu.fileByIndex(resolved.file).path;
4233 return writer.print("comptime(inst=('{s}', %{}) [{}])", .{ file_path, @intFromEnum(resolved.inst), @intFromEnum(cu_id) });4305 return writer.print("comptime(inst=('{}', %{}) [{}])", .{ file_path.fmt(zcu.comp), @intFromEnum(resolved.inst), @intFromEnum(cu_id) });
4234 } else {4306 } else {
4235 return writer.print("comptime(inst=<lost> [{}])", .{@intFromEnum(cu_id)});4307 return writer.print("comptime(inst=<lost> [{}])", .{@intFromEnum(cu_id)});
4236 }4308 }
...@@ -4254,8 +4326,8 @@ fn formatDependee(data: struct { dependee: InternPool.Dependee, zcu: *Zcu }, com...@@ -4254,8 +4326,8 @@ fn formatDependee(data: struct { dependee: InternPool.Dependee, zcu: *Zcu }, com
4254 const info = ti.resolveFull(ip) orelse {4326 const info = ti.resolveFull(ip) orelse {
4255 return writer.writeAll("inst(<lost>)");4327 return writer.writeAll("inst(<lost>)");
4256 };4328 };
4257 const file_path = zcu.fileByIndex(info.file).sub_file_path;4329 const file_path = zcu.fileByIndex(info.file).path;
4258 return writer.print("inst('{s}', %{d})", .{ file_path, @intFromEnum(info.inst) });4330 return writer.print("inst('{}', %{d})", .{ file_path.fmt(zcu.comp), @intFromEnum(info.inst) });
4259 },4331 },
4260 .nav_val => |nav| {4332 .nav_val => |nav| {
4261 const fqn = ip.getNav(nav).fqn;4333 const fqn = ip.getNav(nav).fqn;
...@@ -4271,30 +4343,26 @@ fn formatDependee(data: struct { dependee: InternPool.Dependee, zcu: *Zcu }, com...@@ -4271,30 +4343,26 @@ fn formatDependee(data: struct { dependee: InternPool.Dependee, zcu: *Zcu }, com
4271 else => unreachable,4343 else => unreachable,
4272 },4344 },
4273 .zon_file => |file| {4345 .zon_file => |file| {
4274 const file_path = zcu.fileByIndex(file).sub_file_path;4346 const file_path = zcu.fileByIndex(file).path;
4275 return writer.print("zon_file('{s}')", .{file_path});4347 return writer.print("zon_file('{}')", .{file_path.fmt(zcu.comp)});
4276 },4348 },
4277 .embed_file => |ef_idx| {4349 .embed_file => |ef_idx| {
4278 const ef = ef_idx.get(zcu);4350 const ef = ef_idx.get(zcu);
4279 return writer.print("embed_file('{s}')", .{std.fs.path.fmtJoin(&.{4351 return writer.print("embed_file('{}')", .{ef.path.fmt(zcu.comp)});
4280 ef.owner.root.root_dir.path orelse "",
4281 ef.owner.root.sub_path,
4282 ef.sub_file_path.toSlice(ip),
4283 })});
4284 },4352 },
4285 .namespace => |ti| {4353 .namespace => |ti| {
4286 const info = ti.resolveFull(ip) orelse {4354 const info = ti.resolveFull(ip) orelse {
4287 return writer.writeAll("namespace(<lost>)");4355 return writer.writeAll("namespace(<lost>)");
4288 };4356 };
4289 const file_path = zcu.fileByIndex(info.file).sub_file_path;4357 const file_path = zcu.fileByIndex(info.file).path;
4290 return writer.print("namespace('{s}', %{d})", .{ file_path, @intFromEnum(info.inst) });4358 return writer.print("namespace('{}', %{d})", .{ file_path.fmt(zcu.comp), @intFromEnum(info.inst) });
4291 },4359 },
4292 .namespace_name => |k| {4360 .namespace_name => |k| {
4293 const info = k.namespace.resolveFull(ip) orelse {4361 const info = k.namespace.resolveFull(ip) orelse {
4294 return writer.print("namespace(<lost>, '{}')", .{k.name.fmt(ip)});4362 return writer.print("namespace(<lost>, '{}')", .{k.name.fmt(ip)});
4295 };4363 };
4296 const file_path = zcu.fileByIndex(info.file).sub_file_path;4364 const file_path = zcu.fileByIndex(info.file).path;
4297 return writer.print("namespace('{s}', %{d}, '{}')", .{ file_path, @intFromEnum(info.inst), k.name.fmt(ip) });4365 return writer.print("namespace('{}', %{d}, '{}')", .{ file_path.fmt(zcu.comp), @intFromEnum(info.inst), k.name.fmt(ip) });
4298 },4366 },
4299 .memoized_state => return writer.writeAll("memoized_state"),4367 .memoized_state => return writer.writeAll("memoized_state"),
4300 }4368 }
...@@ -4511,3 +4579,114 @@ pub fn codegenFailTypeMsg(zcu: *Zcu, ty_index: InternPool.Index, msg: *ErrorMsg)...@@ -4511,3 +4579,114 @@ pub fn codegenFailTypeMsg(zcu: *Zcu, ty_index: InternPool.Index, msg: *ErrorMsg)
4511 zcu.failed_types.putAssumeCapacityNoClobber(ty_index, msg);4579 zcu.failed_types.putAssumeCapacityNoClobber(ty_index, msg);
4512 return error.CodegenFail;4580 return error.CodegenFail;
4513}4581}
4582
4583/// Asserts that `zcu.multi_module_err != null`.
4584pub fn addFileInMultipleModulesError(
4585 zcu: *Zcu,
4586 eb: *std.zig.ErrorBundle.Wip,
4587) !void {
4588 const gpa = zcu.gpa;
4589
4590 const info = zcu.multi_module_err.?;
4591 const file = info.file;
4592
4593 // error: file exists in modules 'root.foo' and 'root.bar'
4594 // note: files must belong to only one module
4595 // note: file is imported here
4596 // note: which is imported here
4597 // note: which is the root of module 'root.foo' imported here
4598 // note: file is the root of module 'root.bar' imported here
4599
4600 const file_src = try zcu.fileByIndex(file).errorBundleWholeFileSrc(zcu, eb);
4601 const root_msg = try eb.printString("file exists in modules '{s}' and '{s}'", .{
4602 info.modules[0].fully_qualified_name,
4603 info.modules[1].fully_qualified_name,
4604 });
4605
4606 var notes: std.ArrayListUnmanaged(std.zig.ErrorBundle.MessageIndex) = .empty;
4607 defer notes.deinit(gpa);
4608
4609 try notes.append(gpa, try eb.addErrorMessage(.{
4610 .msg = try eb.addString("files must belong to only one module"),
4611 .src_loc = file_src,
4612 }));
4613
4614 try zcu.explainWhyFileIsInModule(eb, &notes, file, info.modules[0], info.refs[0]);
4615 try zcu.explainWhyFileIsInModule(eb, &notes, file, info.modules[1], info.refs[1]);
4616
4617 try eb.addRootErrorMessage(.{
4618 .msg = root_msg,
4619 .src_loc = file_src,
4620 .notes_len = @intCast(notes.items.len),
4621 });
4622 const notes_start = try eb.reserveNotes(@intCast(notes.items.len));
4623 const notes_slice: []std.zig.ErrorBundle.MessageIndex = @ptrCast(eb.extra.items[notes_start..]);
4624 @memcpy(notes_slice, notes.items);
4625}
4626
4627fn explainWhyFileIsInModule(
4628 zcu: *Zcu,
4629 eb: *std.zig.ErrorBundle.Wip,
4630 notes_out: *std.ArrayListUnmanaged(std.zig.ErrorBundle.MessageIndex),
4631 file: File.Index,
4632 in_module: *Package.Module,
4633 ref: File.Reference,
4634) !void {
4635 const gpa = zcu.gpa;
4636
4637 // error: file is the root of module 'foo'
4638 //
4639 // error: file is imported here by the root of module 'foo'
4640 //
4641 // error: file is imported here
4642 // note: which is imported here
4643 // note: which is imported here by the root of module 'foo'
4644
4645 var import = switch (ref) {
4646 .analysis_root => |mod| {
4647 assert(mod == in_module);
4648 try notes_out.append(gpa, try eb.addErrorMessage(.{
4649 .msg = try eb.printString("file is the root of module '{s}'", .{mod.fully_qualified_name}),
4650 .src_loc = try zcu.fileByIndex(file).errorBundleWholeFileSrc(zcu, eb),
4651 }));
4652 return;
4653 },
4654 .import => |import| if (import.module) |mod| {
4655 assert(mod == in_module);
4656 try notes_out.append(gpa, try eb.addErrorMessage(.{
4657 .msg = try eb.printString("file is the root of module '{s}'", .{mod.fully_qualified_name}),
4658 .src_loc = try zcu.fileByIndex(file).errorBundleWholeFileSrc(zcu, eb),
4659 }));
4660 return;
4661 } else import,
4662 };
4663
4664 var is_first = true;
4665 while (true) {
4666 const thing: []const u8 = if (is_first) "file" else "which";
4667 is_first = false;
4668
4669 const import_src = try zcu.fileByIndex(import.importer).errorBundleTokenSrc(import.tok, zcu, eb);
4670
4671 const importer_ref = zcu.alive_files.get(import.importer).?;
4672 const importer_root: ?*Package.Module = switch (importer_ref) {
4673 .analysis_root => |mod| mod,
4674 .import => |i| i.module,
4675 };
4676
4677 if (importer_root) |m| {
4678 try notes_out.append(gpa, try eb.addErrorMessage(.{
4679 .msg = try eb.printString("{s} is imported here by the root of module '{s}'", .{ thing, m.fully_qualified_name }),
4680 .src_loc = import_src,
4681 }));
4682 return;
4683 }
4684
4685 try notes_out.append(gpa, try eb.addErrorMessage(.{
4686 .msg = try eb.printString("{s} is imported here", .{thing}),
4687 .src_loc = import_src,
4688 }));
4689
4690 import = importer_ref.import;
4691 }
4692}
src/Zcu/PerThread.zig+529-334
...@@ -8,23 +8,26 @@ const Ast = std.zig.Ast;...@@ -8,23 +8,26 @@ const Ast = std.zig.Ast;
8const AstGen = std.zig.AstGen;8const AstGen = std.zig.AstGen;
9const BigIntConst = std.math.big.int.Const;9const BigIntConst = std.math.big.int.Const;
10const BigIntMutable = std.math.big.int.Mutable;10const BigIntMutable = std.math.big.int.Mutable;
11const Builtin = @import("../Builtin.zig");
11const build_options = @import("build_options");12const build_options = @import("build_options");
12const builtin = @import("builtin");13const builtin = @import("builtin");
13const Cache = std.Build.Cache;14const Cache = std.Build.Cache;
14const dev = @import("../dev.zig");15const dev = @import("../dev.zig");
15const InternPool = @import("../InternPool.zig");16const InternPool = @import("../InternPool.zig");
16const AnalUnit = InternPool.AnalUnit;17const AnalUnit = InternPool.AnalUnit;
17const isUpDir = @import("../introspect.zig").isUpDir;18const introspect = @import("../introspect.zig");
18const Liveness = @import("../Liveness.zig");19const Liveness = @import("../Liveness.zig");
19const log = std.log.scoped(.zcu);20const log = std.log.scoped(.zcu);
20const Module = @import("../Package.zig").Module;21const Module = @import("../Package.zig").Module;
21const Sema = @import("../Sema.zig");22const Sema = @import("../Sema.zig");
22const std = @import("std");23const std = @import("std");
24const mem = std.mem;
23const target_util = @import("../target.zig");25const target_util = @import("../target.zig");
24const trace = @import("../tracy.zig").trace;26const trace = @import("../tracy.zig").trace;
25const Type = @import("../Type.zig");27const Type = @import("../Type.zig");
26const Value = @import("../Value.zig");28const Value = @import("../Value.zig");
27const Zcu = @import("../Zcu.zig");29const Zcu = @import("../Zcu.zig");
30const Compilation = @import("../Compilation.zig");
28const Zir = std.zig.Zir;31const Zir = std.zig.Zir;
29const Zoir = std.zig.Zoir;32const Zoir = std.zig.Zoir;
30const ZonGen = std.zig.ZonGen;33const ZonGen = std.zig.ZonGen;
...@@ -50,16 +53,9 @@ fn deinitFile(pt: Zcu.PerThread, file_index: Zcu.File.Index) void {...@@ -50,16 +53,9 @@ fn deinitFile(pt: Zcu.PerThread, file_index: Zcu.File.Index) void {
50 const zcu = pt.zcu;53 const zcu = pt.zcu;
51 const gpa = zcu.gpa;54 const gpa = zcu.gpa;
52 const file = zcu.fileByIndex(file_index);55 const file = zcu.fileByIndex(file_index);
53 const is_builtin = file.mod.isBuiltin();56 log.debug("deinit File {}", .{file.path.fmt(zcu.comp)});
54 log.debug("deinit File {s}", .{file.sub_file_path});57 file.path.deinit(gpa);
55 if (is_builtin) {58 file.unload(gpa);
56 file.unloadTree(gpa);
57 file.unloadZir(gpa);
58 } else {
59 gpa.free(file.sub_file_path);
60 file.unload(gpa);
61 }
62 file.references.deinit(gpa);
63 if (file.prev_zir) |prev_zir| {59 if (file.prev_zir) |prev_zir| {
64 prev_zir.deinit(gpa);60 prev_zir.deinit(gpa);
65 gpa.destroy(prev_zir);61 gpa.destroy(prev_zir);
...@@ -70,20 +66,19 @@ fn deinitFile(pt: Zcu.PerThread, file_index: Zcu.File.Index) void {...@@ -70,20 +66,19 @@ fn deinitFile(pt: Zcu.PerThread, file_index: Zcu.File.Index) void {
70pub fn destroyFile(pt: Zcu.PerThread, file_index: Zcu.File.Index) void {66pub fn destroyFile(pt: Zcu.PerThread, file_index: Zcu.File.Index) void {
71 const gpa = pt.zcu.gpa;67 const gpa = pt.zcu.gpa;
72 const file = pt.zcu.fileByIndex(file_index);68 const file = pt.zcu.fileByIndex(file_index);
73 const is_builtin = file.mod.isBuiltin();
74 pt.deinitFile(file_index);69 pt.deinitFile(file_index);
75 if (!is_builtin) gpa.destroy(file);70 gpa.destroy(file);
76}71}
7772
78/// Ensures that `file` has up-to-date ZIR. If not, loads the ZIR cache or runs73/// Ensures that `file` has up-to-date ZIR. If not, loads the ZIR cache or runs
79/// AstGen as needed. Also updates `file.status`.74/// AstGen as needed. Also updates `file.status`. Does not assume that `file.mod`
75/// is populated. Does not return `error.AnalysisFail` on AstGen failures.
80pub fn updateFile(76pub fn updateFile(
81 pt: Zcu.PerThread,77 pt: Zcu.PerThread,
78 file_index: Zcu.File.Index,
82 file: *Zcu.File,79 file: *Zcu.File,
83 path_digest: Cache.BinDigest,
84) !void {80) !void {
85 dev.check(.ast_gen);81 dev.check(.ast_gen);
86 assert(!file.mod.isBuiltin());
8782
88 const tracy = trace(@src());83 const tracy = trace(@src());
89 defer tracy.end();84 defer tracy.end();
...@@ -93,13 +88,20 @@ pub fn updateFile(...@@ -93,13 +88,20 @@ pub fn updateFile(
93 const gpa = zcu.gpa;88 const gpa = zcu.gpa;
9489
95 // In any case we need to examine the stat of the file to determine the course of action.90 // In any case we need to examine the stat of the file to determine the course of action.
96 var source_file = try file.mod.root.openFile(file.sub_file_path, .{});91 var source_file = f: {
92 const dir, const sub_path = file.path.openInfo(comp.dirs);
93 break :f try dir.openFile(sub_path, .{});
94 };
97 defer source_file.close();95 defer source_file.close();
9896
99 const stat = try source_file.stat();97 const stat = try source_file.stat();
10098
101 const want_local_cache = file.mod == zcu.main_mod;99 const want_local_cache = switch (file.path.root) {
102 const hex_digest = Cache.binToHex(path_digest);100 .none, .local_cache => true,
101 .global_cache, .zig_lib => false,
102 };
103
104 const hex_digest = Cache.binToHex(file.path.digest());
103 const cache_directory = if (want_local_cache) zcu.local_zir_cache else zcu.global_zir_cache;105 const cache_directory = if (want_local_cache) zcu.local_zir_cache else zcu.global_zir_cache;
104 const zir_dir = cache_directory.handle;106 const zir_dir = cache_directory.handle;
105107
...@@ -107,8 +109,8 @@ pub fn updateFile(...@@ -107,8 +109,8 @@ pub fn updateFile(
107 var lock: std.fs.File.Lock = switch (file.status) {109 var lock: std.fs.File.Lock = switch (file.status) {
108 .never_loaded, .retryable_failure => lock: {110 .never_loaded, .retryable_failure => lock: {
109 // First, load the cached ZIR code, if any.111 // First, load the cached ZIR code, if any.
110 log.debug("AstGen checking cache: {s} (local={}, digest={s})", .{112 log.debug("AstGen checking cache: {} (local={}, digest={s})", .{
111 file.sub_file_path, want_local_cache, &hex_digest,113 file.path.fmt(comp), want_local_cache, &hex_digest,
112 });114 });
113115
114 break :lock .shared;116 break :lock .shared;
...@@ -120,18 +122,18 @@ pub fn updateFile(...@@ -120,18 +122,18 @@ pub fn updateFile(
120 stat.inode == file.stat.inode;122 stat.inode == file.stat.inode;
121123
122 if (unchanged_metadata) {124 if (unchanged_metadata) {
123 log.debug("unmodified metadata of file: {s}", .{file.sub_file_path});125 log.debug("unmodified metadata of file: {}", .{file.path.fmt(comp)});
124 return;126 return;
125 }127 }
126128
127 log.debug("metadata changed: {s}", .{file.sub_file_path});129 log.debug("metadata changed: {}", .{file.path.fmt(comp)});
128130
129 break :lock .exclusive;131 break :lock .exclusive;
130 },132 },
131 };133 };
132134
133 // The old compile error, if any, is no longer relevant.135 // The old compile error, if any, is no longer relevant.
134 pt.lockAndClearFileCompileError(file);136 pt.lockAndClearFileCompileError(file_index, file);
135137
136 // If `zir` is not null, and `prev_zir` is null, then `TrackedInst`s are associated with `zir`.138 // If `zir` is not null, and `prev_zir` is null, then `TrackedInst`s are associated with `zir`.
137 // We need to keep it around!139 // We need to keep it around!
...@@ -211,12 +213,12 @@ pub fn updateFile(...@@ -211,12 +213,12 @@ pub fn updateFile(
211 };213 };
212 switch (result) {214 switch (result) {
213 .success => {215 .success => {
214 log.debug("AstGen cached success: {s}", .{file.sub_file_path});216 log.debug("AstGen cached success: {}", .{file.path.fmt(comp)});
215 break false;217 break false;
216 },218 },
217 .invalid => {},219 .invalid => {},
218 .truncated => log.warn("unexpected EOF reading cached ZIR for {s}", .{file.sub_file_path}),220 .truncated => log.warn("unexpected EOF reading cached ZIR for {}", .{file.path.fmt(comp)}),
219 .stale => log.debug("AstGen cache stale: {s}", .{file.sub_file_path}),221 .stale => log.debug("AstGen cache stale: {}", .{file.path.fmt(comp)}),
220 }222 }
221223
222 // If we already have the exclusive lock then it is our job to update.224 // If we already have the exclusive lock then it is our job to update.
...@@ -255,22 +257,22 @@ pub fn updateFile(...@@ -255,22 +257,22 @@ pub fn updateFile(
255 file.zir = try AstGen.generate(gpa, file.tree.?);257 file.zir = try AstGen.generate(gpa, file.tree.?);
256 Zcu.saveZirCache(gpa, cache_file, stat, file.zir.?) catch |err| switch (err) {258 Zcu.saveZirCache(gpa, cache_file, stat, file.zir.?) catch |err| switch (err) {
257 error.OutOfMemory => |e| return e,259 error.OutOfMemory => |e| return e,
258 else => log.warn("unable to write cached ZIR code for {}{s} to {}{s}: {s}", .{260 else => log.warn("unable to write cached ZIR code for {} to {}{s}: {s}", .{
259 file.mod.root, file.sub_file_path, cache_directory, &hex_digest, @errorName(err),261 file.path.fmt(comp), cache_directory, &hex_digest, @errorName(err),
260 }),262 }),
261 };263 };
262 },264 },
263 .zon => {265 .zon => {
264 file.zoir = try ZonGen.generate(gpa, file.tree.?, .{});266 file.zoir = try ZonGen.generate(gpa, file.tree.?, .{});
265 Zcu.saveZoirCache(cache_file, stat, file.zoir.?) catch |err| {267 Zcu.saveZoirCache(cache_file, stat, file.zoir.?) catch |err| {
266 log.warn("unable to write cached ZOIR code for {}{s} to {}{s}: {s}", .{268 log.warn("unable to write cached ZOIR code for {} to {}{s}: {s}", .{
267 file.mod.root, file.sub_file_path, cache_directory, &hex_digest, @errorName(err),269 file.path.fmt(comp), cache_directory, &hex_digest, @errorName(err),
268 });270 });
269 };271 };
270 },272 },
271 }273 }
272274
273 log.debug("AstGen fresh success: {s}", .{file.sub_file_path});275 log.debug("AstGen fresh success: {}", .{file.path.fmt(comp)});
274 }276 }
275277
276 file.stat = .{278 file.stat = .{
...@@ -287,7 +289,7 @@ pub fn updateFile(...@@ -287,7 +289,7 @@ pub fn updateFile(
287 if (file.zir.?.hasCompileErrors()) {289 if (file.zir.?.hasCompileErrors()) {
288 comp.mutex.lock();290 comp.mutex.lock();
289 defer comp.mutex.unlock();291 defer comp.mutex.unlock();
290 try zcu.failed_files.putNoClobber(gpa, file, null);292 try zcu.failed_files.putNoClobber(gpa, file_index, null);
291 }293 }
292 if (file.zir.?.loweringFailed()) {294 if (file.zir.?.loweringFailed()) {
293 file.status = .astgen_failure;295 file.status = .astgen_failure;
...@@ -300,7 +302,7 @@ pub fn updateFile(...@@ -300,7 +302,7 @@ pub fn updateFile(
300 file.status = .astgen_failure;302 file.status = .astgen_failure;
301 comp.mutex.lock();303 comp.mutex.lock();
302 defer comp.mutex.unlock();304 defer comp.mutex.unlock();
303 try zcu.failed_files.putNoClobber(gpa, file, null);305 try zcu.failed_files.putNoClobber(gpa, file_index, null);
304 } else {306 } else {
305 file.status = .success;307 file.status = .success;
306 }308 }
...@@ -310,8 +312,7 @@ pub fn updateFile(...@@ -310,8 +312,7 @@ pub fn updateFile(
310 switch (file.status) {312 switch (file.status) {
311 .never_loaded => unreachable,313 .never_loaded => unreachable,
312 .retryable_failure => unreachable,314 .retryable_failure => unreachable,
313 .astgen_failure => return error.AnalysisFail,315 .astgen_failure, .success => {},
314 .success => return,
315 }316 }
316}317}
317318
...@@ -388,9 +389,18 @@ pub fn updateZirRefs(pt: Zcu.PerThread) Allocator.Error!void {...@@ -388,9 +389,18 @@ pub fn updateZirRefs(pt: Zcu.PerThread) Allocator.Error!void {
388 var updated_files: std.AutoArrayHashMapUnmanaged(Zcu.File.Index, UpdatedFile) = .empty;389 var updated_files: std.AutoArrayHashMapUnmanaged(Zcu.File.Index, UpdatedFile) = .empty;
389 defer cleanupUpdatedFiles(gpa, &updated_files);390 defer cleanupUpdatedFiles(gpa, &updated_files);
390391
391 for (zcu.import_table.values()) |file_index| {392 for (zcu.import_table.keys()) |file_index| {
393 if (!zcu.alive_files.contains(file_index)) continue;
392 const file = zcu.fileByIndex(file_index);394 const file = zcu.fileByIndex(file_index);
393 assert(file.status == .success);395 assert(file.status == .success);
396 if (file.module_changed) {
397 try updated_files.putNoClobber(gpa, file_index, .{
398 .file = file,
399 // We intentionally don't map any instructions here; that's the point, the whole file is outdated!
400 .inst_map = .{},
401 });
402 continue;
403 }
394 switch (file.getMode()) {404 switch (file.getMode()) {
395 .zig => {}, // logic below405 .zig => {}, // logic below
396 .zon => {406 .zon => {
...@@ -540,10 +550,12 @@ pub fn updateZirRefs(pt: Zcu.PerThread) Allocator.Error!void {...@@ -540,10 +550,12 @@ pub fn updateZirRefs(pt: Zcu.PerThread) Allocator.Error!void {
540 for (updated_files.keys(), updated_files.values()) |file_index, updated_file| {550 for (updated_files.keys(), updated_files.values()) |file_index, updated_file| {
541 const file = updated_file.file;551 const file = updated_file.file;
542552
543 const prev_zir = file.prev_zir.?;553 if (file.prev_zir) |prev_zir| {
544 file.prev_zir = null;554 prev_zir.deinit(gpa);
545 prev_zir.deinit(gpa);555 gpa.destroy(prev_zir);
546 gpa.destroy(prev_zir);556 file.prev_zir = null;
557 }
558 file.module_changed = false;
547559
548 // For every file which has changed, re-scan the namespace of the file's root struct type.560 // For every file which has changed, re-scan the namespace of the file's root struct type.
549 // These types are special-cased because they don't have an enclosing declaration which will561 // These types are special-cased because they don't have an enclosing declaration which will
...@@ -661,9 +673,9 @@ fn analyzeMemoizedState(pt: Zcu.PerThread, stage: InternPool.MemoizedStateStage)...@@ -661,9 +673,9 @@ fn analyzeMemoizedState(pt: Zcu.PerThread, stage: InternPool.MemoizedStateStage)
661 // * The type `std`, and its namespace673 // * The type `std`, and its namespace
662 // * The type `std.builtin`, and its namespace674 // * The type `std.builtin`, and its namespace
663 // * A semi-reasonable source location675 // * A semi-reasonable source location
664 const std_file_imported = pt.importPkg(zcu.std_mod) catch return error.AnalysisFail;676 const std_file_index = zcu.module_roots.get(zcu.std_mod).?.unwrap().?;
665 try pt.ensureFileAnalyzed(std_file_imported.file_index);677 try pt.ensureFileAnalyzed(std_file_index);
666 const std_type: Type = .fromInterned(zcu.fileRootType(std_file_imported.file_index));678 const std_type: Type = .fromInterned(zcu.fileRootType(std_file_index));
667 const std_namespace = std_type.getNamespaceIndex(zcu);679 const std_namespace = std_type.getNamespaceIndex(zcu);
668 try pt.ensureNamespaceUpToDate(std_namespace);680 try pt.ensureNamespaceUpToDate(std_namespace);
669 const builtin_str = try ip.getOrPutString(gpa, pt.tid, "builtin", .no_embedded_nulls);681 const builtin_str = try ip.getOrPutString(gpa, pt.tid, "builtin", .no_embedded_nulls);
...@@ -675,7 +687,7 @@ fn analyzeMemoizedState(pt: Zcu.PerThread, stage: InternPool.MemoizedStateStage)...@@ -675,7 +687,7 @@ fn analyzeMemoizedState(pt: Zcu.PerThread, stage: InternPool.MemoizedStateStage)
675 try pt.ensureNamespaceUpToDate(builtin_namespace);687 try pt.ensureNamespaceUpToDate(builtin_namespace);
676 const src: Zcu.LazySrcLoc = .{688 const src: Zcu.LazySrcLoc = .{
677 .base_node_inst = builtin_type.typeDeclInst(zcu).?,689 .base_node_inst = builtin_type.typeDeclInst(zcu).?,
678 .offset = .entire_file,690 .offset = .{ .byte_abs = 0 },
679 };691 };
680692
681 var analysis_arena: std.heap.ArenaAllocator = .init(gpa);693 var analysis_arena: std.heap.ArenaAllocator = .init(gpa);
...@@ -1250,7 +1262,7 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr...@@ -1250,7 +1262,7 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr
12501262
1251 if (!try nav_ty.hasRuntimeBitsSema(pt)) {1263 if (!try nav_ty.hasRuntimeBitsSema(pt)) {
1252 if (zcu.comp.config.use_llvm) break :queue_codegen;1264 if (zcu.comp.config.use_llvm) break :queue_codegen;
1253 if (file.mod.strip) break :queue_codegen;1265 if (file.mod.?.strip) break :queue_codegen;
1254 }1266 }
12551267
1256 // This job depends on any resolve_type_fully jobs queued up before it.1268 // This job depends on any resolve_type_fully jobs queued up before it.
...@@ -1730,13 +1742,12 @@ pub fn linkerUpdateFunc(pt: Zcu.PerThread, func_index: InternPool.Index, air: Ai...@@ -1730,13 +1742,12 @@ pub fn linkerUpdateFunc(pt: Zcu.PerThread, func_index: InternPool.Index, air: Ai
1730 }1742 }
1731}1743}
17321744
1733/// https://github.com/ziglang/zig/issues/143071745pub fn semaMod(pt: Zcu.PerThread, mod: *Module) !void {
1734pub fn semaPkg(pt: Zcu.PerThread, pkg: *Module) !void {
1735 dev.check(.sema);1746 dev.check(.sema);
1736 const import_file_result = try pt.importPkg(pkg);1747 const file_index = pt.zcu.module_roots.get(mod).?.unwrap().?;
1737 const root_type = pt.zcu.fileRootType(import_file_result.file_index);1748 const root_type = pt.zcu.fileRootType(file_index);
1738 if (root_type == .none) {1749 if (root_type == .none) {
1739 return pt.semaFile(import_file_result.file_index);1750 return pt.semaFile(file_index);
1740 }1751 }
1741}1752}
17421753
...@@ -1808,7 +1819,7 @@ fn createFileRootStruct(...@@ -1808,7 +1819,7 @@ fn createFileRootStruct(
1808 try zcu.comp.queueJob(.{ .resolve_type_fully = wip_ty.index });1819 try zcu.comp.queueJob(.{ .resolve_type_fully = wip_ty.index });
1809 codegen_type: {1820 codegen_type: {
1810 if (zcu.comp.config.use_llvm) break :codegen_type;1821 if (zcu.comp.config.use_llvm) break :codegen_type;
1811 if (file.mod.strip) break :codegen_type;1822 if (file.mod.?.strip) break :codegen_type;
1812 // This job depends on any resolve_type_fully jobs queued up before it.1823 // This job depends on any resolve_type_fully jobs queued up before it.
1813 try zcu.comp.queueJob(.{ .codegen_type = wip_ty.index });1824 try zcu.comp.queueJob(.{ .codegen_type = wip_ty.index });
1814 }1825 }
...@@ -1829,7 +1840,7 @@ fn updateFileNamespace(pt: Zcu.PerThread, file_index: Zcu.File.Index) Allocator....@@ -1829,7 +1840,7 @@ fn updateFileNamespace(pt: Zcu.PerThread, file_index: Zcu.File.Index) Allocator.
1829 if (file_root_type == .none) return;1840 if (file_root_type == .none) return;
18301841
1831 log.debug("updateFileNamespace mod={s} sub_file_path={s}", .{1842 log.debug("updateFileNamespace mod={s} sub_file_path={s}", .{
1832 file.mod.fully_qualified_name,1843 file.mod.?.fully_qualified_name,
1833 file.sub_file_path,1844 file.sub_file_path,
1834 });1845 });
18351846
...@@ -1872,211 +1883,464 @@ fn semaFile(pt: Zcu.PerThread, file_index: Zcu.File.Index) Zcu.SemaError!void {...@@ -1872,211 +1883,464 @@ fn semaFile(pt: Zcu.PerThread, file_index: Zcu.File.Index) Zcu.SemaError!void {
1872 errdefer zcu.intern_pool.remove(pt.tid, struct_ty);1883 errdefer zcu.intern_pool.remove(pt.tid, struct_ty);
1873}1884}
18741885
1875pub fn importPkg(pt: Zcu.PerThread, mod: *Module) Allocator.Error!Zcu.ImportFileResult {1886/// Called by AstGen worker threads when an import is seen. If `new_file` is returned, the caller is
1887/// then responsible for queueing a new AstGen job for the new file.
1888/// Assumes that `comp.mutex` is NOT locked. It will be locked by this function where necessary.
1889pub fn discoverImport(
1890 pt: Zcu.PerThread,
1891 importer_path: Compilation.Path,
1892 import_string: []const u8,
1893) Allocator.Error!union(enum) {
1894 module,
1895 existing_file: Zcu.File.Index,
1896 new_file: struct {
1897 index: Zcu.File.Index,
1898 file: *Zcu.File,
1899 },
1900} {
1876 const zcu = pt.zcu;1901 const zcu = pt.zcu;
1877 const gpa = zcu.gpa;1902 const gpa = zcu.gpa;
18781903
1879 // The resolved path is used as the key in the import table, to detect if1904 if (!mem.endsWith(u8, import_string, ".zig") and !mem.endsWith(u8, import_string, ".zon")) {
1880 // an import refers to the same as another, despite different relative paths1905 return .module;
1881 // or differently mapped package names.1906 }
1882 const resolved_path = try std.fs.path.resolve(gpa, &.{
1883 mod.root.root_dir.path orelse ".",
1884 mod.root.sub_path,
1885 mod.root_src_path,
1886 });
1887 var keep_resolved_path = false;
1888 defer if (!keep_resolved_path) gpa.free(resolved_path);
18891907
1890 const gop = try zcu.import_table.getOrPut(gpa, resolved_path);1908 const new_path = try importer_path.upJoin(gpa, zcu.comp.dirs, import_string);
1909 errdefer new_path.deinit(gpa);
1910
1911 // We're about to do a GOP on `import_table`, so we need the mutex.
1912 zcu.comp.mutex.lock();
1913 defer zcu.comp.mutex.unlock();
1914
1915 const gop = try zcu.import_table.getOrPutAdapted(gpa, new_path, Zcu.ImportTableAdapter{ .zcu = zcu });
1891 errdefer _ = zcu.import_table.pop();1916 errdefer _ = zcu.import_table.pop();
1892 if (gop.found_existing) {1917 if (gop.found_existing) {
1893 const file_index = gop.value_ptr.*;1918 new_path.deinit(gpa); // we didn't need it for `File.path`
1894 const file = zcu.fileByIndex(file_index);1919 return .{ .existing_file = gop.key_ptr.* };
1895 try file.addReference(zcu, .{ .root = mod });
1896 return .{
1897 .file = file,
1898 .file_index = file_index,
1899 .is_new = false,
1900 .is_pkg = true,
1901 };
1902 }
1903
1904 const ip = &zcu.intern_pool;
1905 if (mod.builtin_file) |builtin_file| {
1906 const path_digest = Zcu.computePathDigest(zcu, mod, builtin_file.sub_file_path);
1907 const file_index = try ip.createFile(gpa, pt.tid, .{
1908 .bin_digest = path_digest,
1909 .file = builtin_file,
1910 .root_type = .none,
1911 });
1912 keep_resolved_path = true; // It's now owned by import_table.
1913 gop.value_ptr.* = file_index;
1914 try builtin_file.addReference(zcu, .{ .root = mod });
1915 return .{
1916 .file = builtin_file,
1917 .file_index = file_index,
1918 .is_new = false,
1919 .is_pkg = true,
1920 };
1921 }1920 }
19221921
1923 const sub_file_path = try gpa.dupe(u8, mod.root_src_path);1922 zcu.import_table.lockPointers();
1924 errdefer gpa.free(sub_file_path);1923 defer zcu.import_table.unlockPointers();
1925
1926 const comp = zcu.comp;
1927 if (comp.file_system_inputs) |fsi|
1928 try comp.appendFileSystemInput(fsi, mod.root, sub_file_path);
19291924
1930 const new_file = try gpa.create(Zcu.File);1925 const new_file = try gpa.create(Zcu.File);
1931 errdefer gpa.destroy(new_file);1926 errdefer gpa.destroy(new_file);
19321927
1933 const path_digest = zcu.computePathDigest(mod, sub_file_path);1928 const new_file_index = try zcu.intern_pool.createFile(gpa, pt.tid, .{
1934 const new_file_index = try ip.createFile(gpa, pt.tid, .{1929 .bin_digest = new_path.digest(),
1935 .bin_digest = path_digest,
1936 .file = new_file,1930 .file = new_file,
1937 .root_type = .none,1931 .root_type = .none,
1938 });1932 });
1939 keep_resolved_path = true; // It's now owned by import_table.1933 errdefer comptime unreachable; // because we don't remove the file from the internpool
1940 gop.value_ptr.* = new_file_index;1934
1935 gop.key_ptr.* = new_file_index;
1941 new_file.* = .{1936 new_file.* = .{
1942 .sub_file_path = sub_file_path,1937 .status = .never_loaded,
1938 .path = new_path,
1943 .stat = undefined,1939 .stat = undefined,
1940 .is_builtin = false,
1944 .source = null,1941 .source = null,
1945 .tree = null,1942 .tree = null,
1946 .zir = null,1943 .zir = null,
1947 .zoir = null,1944 .zoir = null,
1948 .status = .never_loaded,1945 .mod = null,
1949 .mod = mod,1946 .sub_file_path = undefined,
1947 .module_changed = false,
1948 .prev_zir = null,
1949 .zoir_invalidated = false,
1950 };1950 };
19511951
1952 try new_file.addReference(zcu, .{ .root = mod });1952 return .{ .new_file = .{
1953 return .{1953 .index = new_file_index,
1954 .file = new_file,1954 .file = new_file,
1955 .file_index = new_file_index,1955 } };
1956 .is_new = true,
1957 .is_pkg = true,
1958 };
1959}1956}
19601957
1961/// Called from a worker thread during AstGen (with the Compilation mutex held).1958pub fn doImport(
1962/// Also called from Sema during semantic analysis.
1963/// Does not attempt to load the file from disk; just returns a corresponding `*Zcu.File`.
1964pub fn importFile(
1965 pt: Zcu.PerThread,1959 pt: Zcu.PerThread,
1966 cur_file: *Zcu.File,1960 /// This file must have its `mod` populated.
1961 importer: *Zcu.File,
1967 import_string: []const u8,1962 import_string: []const u8,
1968) error{1963) error{
1969 OutOfMemory,1964 OutOfMemory,
1970 ModuleNotFound,1965 ModuleNotFound,
1971 ImportOutsideModulePath,1966 IllegalZigImport,
1972 CurrentWorkingDirectoryUnlinked,1967}!struct {
1973}!Zcu.ImportFileResult {1968 file: Zcu.File.Index,
1969 module_root: ?*Module,
1970} {
1974 const zcu = pt.zcu;1971 const zcu = pt.zcu;
1975 const mod = cur_file.mod;1972 const gpa = zcu.gpa;
19761973 const imported_mod: ?*Module = m: {
1977 if (std.mem.eql(u8, import_string, "std")) {1974 if (mem.eql(u8, import_string, "std")) break :m zcu.std_mod;
1978 return pt.importPkg(zcu.std_mod);1975 if (mem.eql(u8, import_string, "root")) break :m zcu.root_mod;
1979 }1976 if (mem.eql(u8, import_string, "builtin")) {
1980 if (std.mem.eql(u8, import_string, "root")) {1977 const opts = importer.mod.?.getBuiltinOptions(zcu.comp.config);
1981 return pt.importPkg(zcu.root_mod);1978 break :m zcu.builtin_modules.get(opts.hash()).?;
1982 }1979 }
1983 if (mod.deps.get(import_string)) |pkg| {1980 break :m importer.mod.?.deps.get(import_string);
1984 return pt.importPkg(pkg);1981 };
1982 if (imported_mod) |mod| {
1983 if (zcu.module_roots.get(mod).?.unwrap()) |file_index| {
1984 return .{
1985 .file = file_index,
1986 .module_root = mod,
1987 };
1988 }
1985 }1989 }
1986 if (!std.mem.endsWith(u8, import_string, ".zig") and1990 if (!std.mem.endsWith(u8, import_string, ".zig") and
1987 !std.mem.endsWith(u8, import_string, ".zon"))1991 !std.mem.endsWith(u8, import_string, ".zon"))
1988 {1992 {
1989 return error.ModuleNotFound;1993 return error.ModuleNotFound;
1990 }1994 }
1995 const path = try importer.path.upJoin(gpa, zcu.comp.dirs, import_string);
1996 defer path.deinit(gpa);
1997 if (try path.isIllegalZigImport(gpa, zcu.comp.dirs)) {
1998 return error.IllegalZigImport;
1999 }
2000 return .{
2001 .file = zcu.import_table.getKeyAdapted(path, Zcu.ImportTableAdapter{ .zcu = zcu }).?,
2002 .module_root = null,
2003 };
2004}
2005/// This is called once during `Compilation.create` and never again. "builtin" modules don't yet
2006/// exist, so are not added to `module_roots` here. They must be added when they are created.
2007pub fn populateModuleRootTable(pt: Zcu.PerThread) error{
2008 OutOfMemory,
2009 /// One of the specified modules had its root source file at an illegal path.
2010 IllegalZigImport,
2011}!void {
2012 const zcu = pt.zcu;
1991 const gpa = zcu.gpa;2013 const gpa = zcu.gpa;
19922014
1993 // The resolved path is used as the key in the import table, to detect if2015 // We'll initially add [mod, undefined] pairs, and when we reach the pair while
1994 // an import refers to the same as another, despite different relative paths2016 // iterating, rewrite the undefined value.
1995 // or differently mapped package names.2017 const roots = &zcu.module_roots;
1996 const resolved_path = try std.fs.path.resolve(gpa, &.{2018 roots.clearRetainingCapacity();
1997 mod.root.root_dir.path orelse ".",2019
1998 mod.root.sub_path,2020 // Start with:
1999 cur_file.sub_file_path,2021 // * `std_mod`, which is the main root of analysis
2000 "..",2022 // * `root_mod`, which is `@import("root")`
2001 import_string,2023 // * `main_mod`, which is a special analysis root in tests (and otherwise equal to `root_mod`)
2002 });2024 // All other modules will be found by traversing their dependency tables.
2025 try roots.ensureTotalCapacity(gpa, 3);
2026 roots.putAssumeCapacity(zcu.std_mod, undefined);
2027 roots.putAssumeCapacity(zcu.root_mod, undefined);
2028 roots.putAssumeCapacity(zcu.main_mod, undefined);
2029 var i: usize = 0;
2030 while (i < roots.count()) {
2031 const mod = roots.keys()[i];
2032 try roots.ensureUnusedCapacity(gpa, mod.deps.count());
2033 for (mod.deps.values()) |dep| {
2034 const gop = roots.getOrPutAssumeCapacity(dep);
2035 _ = gop; // we want to leave the value undefined if it was added
2036 }
20032037
2004 var keep_resolved_path = false;2038 const root_file_out = &roots.values()[i];
2005 defer if (!keep_resolved_path) gpa.free(resolved_path);2039 roots.lockPointers();
2040 defer roots.unlockPointers();
20062041
2007 const gop = try zcu.import_table.getOrPut(gpa, resolved_path);2042 i += 1;
2008 errdefer _ = zcu.import_table.pop();2043
2009 if (gop.found_existing) {2044 if (Zcu.File.modeFromPath(mod.root_src_path) == null) {
2010 const file_index = gop.value_ptr.*;2045 root_file_out.* = .none;
2011 return .{2046 continue;
2012 .file = zcu.fileByIndex(file_index),2047 }
2013 .file_index = file_index,2048
2014 .is_new = false,2049 const path = try mod.root.join(gpa, zcu.comp.dirs, mod.root_src_path);
2015 .is_pkg = false,2050 errdefer path.deinit(gpa);
2051
2052 if (try path.isIllegalZigImport(gpa, zcu.comp.dirs)) {
2053 return error.IllegalZigImport;
2054 }
2055
2056 const gop = try zcu.import_table.getOrPutAdapted(gpa, path, Zcu.ImportTableAdapter{ .zcu = zcu });
2057 errdefer _ = zcu.import_table.pop();
2058
2059 if (gop.found_existing) {
2060 path.deinit(gpa);
2061 root_file_out.* = gop.key_ptr.*.toOptional();
2062 continue;
2063 }
2064
2065 zcu.import_table.lockPointers();
2066 defer zcu.import_table.unlockPointers();
2067
2068 const new_file = try gpa.create(Zcu.File);
2069 errdefer gpa.destroy(new_file);
2070
2071 const new_file_index = try zcu.intern_pool.createFile(gpa, pt.tid, .{
2072 .bin_digest = path.digest(),
2073 .file = new_file,
2074 .root_type = .none,
2075 });
2076 errdefer comptime unreachable; // because we don't remove the file from the internpool
2077
2078 gop.key_ptr.* = new_file_index;
2079 root_file_out.* = new_file_index.toOptional();
2080 new_file.* = .{
2081 .status = .never_loaded,
2082 .path = path,
2083 .stat = undefined,
2084 .is_builtin = false,
2085 .source = null,
2086 .tree = null,
2087 .zir = null,
2088 .zoir = null,
2089 .mod = null,
2090 .sub_file_path = undefined,
2091 .module_changed = false,
2092 .prev_zir = null,
2093 .zoir_invalidated = false,
2016 };2094 };
2017 }2095 }
2096}
20182097
2019 const ip = &zcu.intern_pool;2098/// Clears and re-populates `pt.zcu.alive_files`, and determines the module identity of every alive
2099/// file. If a file's module changes, its `module_changed` flag is set for `updateZirRefs` to see.
2100/// Also clears and re-populates `failed_imports` and `multi_module_err` based on the set of alive
2101/// files.
2102///
2103/// Live files are also added as file system inputs if necessary.
2104///
2105/// Returns whether there is any live file which is failed. Howewver, this function does *not*
2106/// modify `pt.zcu.skip_analysis_this_update`.
2107///
2108/// If an error is returned, `pt.zcu.alive_files` might contain undefined values.
2109pub fn computeAliveFiles(pt: Zcu.PerThread) Allocator.Error!bool {
2110 const zcu = pt.zcu;
2111 const comp = zcu.comp;
2112 const gpa = zcu.gpa;
20202113
2021 const new_file = try gpa.create(Zcu.File);2114 var any_fatal_files = false;
2022 errdefer gpa.destroy(new_file);2115 zcu.multi_module_err = null;
2116 zcu.failed_imports.clearRetainingCapacity();
2117 zcu.alive_files.clearRetainingCapacity();
2118
2119 // This function will iterate the keys of `alive_files`, adding new entries as it discovers
2120 // imports. Once a file is in `alive_files`, it has its `mod` field up-to-date. If conflicting
2121 // imports are discovered for a file, we will set `multi_module_err`. Crucially, this traversal
2122 // is single-threaded, and depends only on the order of the imports map from AstGen, which makes
2123 // its behavior (in terms of which multi module errors are discovered) entirely consistent in a
2124 // multi-threaded environment (where things like file indices could differ between compiler runs).
2125
2126 // The roots of our file liveness analysis will be the analysis roots.
2127 try zcu.alive_files.ensureTotalCapacity(gpa, zcu.analysis_roots.len);
2128 for (zcu.analysis_roots.slice()) |mod| {
2129 const file_index = zcu.module_roots.get(mod).?.unwrap() orelse continue;
2130 const file = zcu.fileByIndex(file_index);
20232131
2024 const resolved_root_path = try std.fs.path.resolve(gpa, &.{2132 file.mod = mod;
2025 mod.root.root_dir.path orelse ".",2133 file.sub_file_path = mod.root_src_path;
2026 mod.root.sub_path,
2027 });
2028 defer gpa.free(resolved_root_path);
20292134
2030 const sub_file_path = p: {2135 zcu.alive_files.putAssumeCapacityNoClobber(file_index, .{ .analysis_root = mod });
2031 const relative = std.fs.path.relative(gpa, resolved_root_path, resolved_path) catch |err| switch (err) {2136 }
2032 error.Unexpected => unreachable,2137
2033 else => |e| return e,2138 var live_check_idx: usize = 0;
2034 };2139 while (live_check_idx < zcu.alive_files.count()) {
2035 errdefer gpa.free(relative);2140 const file_idx = zcu.alive_files.keys()[live_check_idx];
2141 const file = zcu.fileByIndex(file_idx);
2142 live_check_idx += 1;
20362143
2037 if (!isUpDir(relative) and !std.fs.path.isAbsolute(relative)) {2144 switch (file.status) {
2038 break :p relative;2145 .never_loaded => unreachable, // everything reachable is loaded by the AstGen workers
2146 .retryable_failure, .astgen_failure => any_fatal_files = true,
2147 .success => {},
2039 }2148 }
2040 return error.ImportOutsideModulePath;
2041 };
2042 errdefer gpa.free(sub_file_path);
20432149
2044 log.debug("new importFile. resolved_root_path={s}, resolved_path={s}, sub_file_path={s}, import_string={s}", .{2150 try comp.appendFileSystemInput(file.path);
2045 resolved_root_path, resolved_path, sub_file_path, import_string,2151
2046 });2152 switch (file.getMode()) {
2153 .zig => {}, // continue to logic below
2154 .zon => continue, // ZON can't import anything
2155 }
2156
2157 if (file.status != .success) continue; // ZIR not valid if there was a file failure
2158
2159 const zir = file.zir.?;
2160 const imports_index = zir.extra[@intFromEnum(Zir.ExtraIndex.imports)];
2161 if (imports_index == 0) continue; // this Zig file has no imports
2162 const extra = zir.extraData(Zir.Inst.Imports, imports_index);
2163 var extra_index = extra.end;
2164 try zcu.alive_files.ensureUnusedCapacity(gpa, extra.data.imports_len);
2165 for (0..extra.data.imports_len) |_| {
2166 const item = zir.extraData(Zir.Inst.Imports.Item, extra_index);
2167 extra_index = item.end;
2168 const import_path = zir.nullTerminatedString(item.data.name);
2169
2170 if (std.mem.eql(u8, import_path, "builtin")) {
2171 // We've not necessarily generated builtin modules yet, so `doImport` could fail. Instead,
2172 // create the module here. Then, since we know that `builtin.zig` doesn't have an error and
2173 // has no imports other than 'std', we can just continue onto the next import.
2174 try pt.updateBuiltinModule(file.mod.?.getBuiltinOptions(comp.config));
2175 continue;
2176 }
2177
2178 const res = pt.doImport(file, import_path) catch |err| switch (err) {
2179 error.OutOfMemory => |e| return e,
2180 error.ModuleNotFound => {
2181 // It'd be nice if this were a file-level error, but allowing this turns out to
2182 // be quite important in practice, e.g. for optional dependencies whose import
2183 // is behind a comptime condition. So, the error here happens in `Sema` instead.
2184 continue;
2185 },
2186 error.IllegalZigImport => {
2187 try zcu.failed_imports.append(gpa, .{
2188 .file_index = file_idx,
2189 .import_string = item.data.name,
2190 .import_token = item.data.token,
2191 .kind = .illegal_zig_import,
2192 });
2193 continue;
2194 },
2195 };
2196
2197 // If the import was not of a module, we propagate our own module.
2198 const imported_mod = res.module_root orelse file.mod.?;
2199 const imported_file = zcu.fileByIndex(res.file);
2200
2201 const imported_ref: Zcu.File.Reference = .{ .import = .{
2202 .importer = file_idx,
2203 .tok = item.data.token,
2204 .module = res.module_root,
2205 } };
2206
2207 const gop = zcu.alive_files.getOrPutAssumeCapacity(res.file);
2208 if (gop.found_existing) {
2209 // This means `imported_file.mod` is already populated. If it doesn't match
2210 // `imported_mod`, then this file exists in multiple modules.
2211 if (imported_file.mod.? != imported_mod) {
2212 // We only report the first multi-module error we see. Thanks to this traversal
2213 // being deterministic, this doesn't raise consistency issues. Moreover, it's a
2214 // useful behavior; we know that this error can be reached *without* realising
2215 // that any other files are multi-module, so it's probably approximately where
2216 // the problem "begins". Any compilation with a multi-module file is likely to
2217 // have a huge number of them by transitive imports, so just reporting this one
2218 // hopefully keeps the error focused.
2219 zcu.multi_module_err = .{
2220 .file = file_idx,
2221 .modules = .{ imported_file.mod.?, imported_mod },
2222 .refs = .{ gop.value_ptr.*, imported_ref },
2223 };
2224 // If we discover a multi-module error, it's the only error which matters, and we
2225 // can't discern any useful information about the file's own imports; so just do
2226 // an early exit now we've populated `zcu.multi_module_err`.
2227 return any_fatal_files;
2228 }
2229 continue;
2230 }
2231 // We're the first thing we've found referencing `res.file`.
2232 gop.value_ptr.* = imported_ref;
2233 if (imported_file.mod) |m| {
2234 if (m == imported_mod) {
2235 // Great, the module and sub path are already populated correctly.
2236 continue;
2237 }
2238 }
2239 // We need to set the file's module, meaning we also need to compute its sub path.
2240 // This string is externally managed and has a lifetime at least equal to the
2241 // lifetime of `imported_file`. `null` means the file is outside its module root.
2242 switch (imported_file.path.isNested(imported_mod.root)) {
2243 .yes => |sub_path| {
2244 if (imported_file.mod != null) {
2245 // There was a module from a previous update; instruct `updateZirRefs` to
2246 // invalidate everything.
2247 imported_file.module_changed = true;
2248 }
2249 imported_file.mod = imported_mod;
2250 imported_file.sub_file_path = sub_path;
2251 },
2252 .different_roots, .no => {
2253 try zcu.failed_imports.append(gpa, .{
2254 .file_index = file_idx,
2255 .import_string = item.data.name,
2256 .import_token = item.data.token,
2257 .kind = .file_outside_module_root,
2258 });
2259 _ = zcu.alive_files.pop(); // we failed to populate `mod`/`sub_file_path`
2260 },
2261 }
2262 }
2263 }
20472264
2265 return any_fatal_files;
2266}
2267
2268/// Ensures that the `@import("builtin")` module corresponding to `opts` is available in
2269/// `builtin_modules`, and that its file is populated. Also ensures the file on disk is
2270/// up-to-date, setting a misc failure if updating it fails.
2271/// Asserts that the imported `builtin.zig` has no ZIR errors, and that it has only one
2272/// import, which is 'std'.
2273pub fn updateBuiltinModule(pt: Zcu.PerThread, opts: Builtin) Allocator.Error!void {
2274 const zcu = pt.zcu;
2048 const comp = zcu.comp;2275 const comp = zcu.comp;
2049 if (comp.file_system_inputs) |fsi|2276 const gpa = zcu.gpa;
2050 try comp.appendFileSystemInput(fsi, mod.root, sub_file_path);
20512277
2052 const path_digest = zcu.computePathDigest(mod, sub_file_path);2278 const gop = try zcu.builtin_modules.getOrPut(gpa, opts.hash());
2053 const new_file_index = try ip.createFile(gpa, pt.tid, .{2279 if (gop.found_existing) return; // the `File` is up-to-date
2054 .bin_digest = path_digest,2280 errdefer _ = zcu.builtin_modules.pop();
2055 .file = new_file,2281
2056 .root_type = .none,2282 const mod: *Module = try .createBuiltin(comp.arena, opts, comp.dirs);
2057 });2283 assert(std.mem.eql(u8, &mod.getBuiltinOptions(comp.config).hash(), gop.key_ptr)); // builtin is its own builtin
2058 keep_resolved_path = true; // It's now owned by import_table.2284
2059 gop.value_ptr.* = new_file_index;2285 const path = try mod.root.join(gpa, comp.dirs, "builtin.zig");
2060 new_file.* = .{2286 errdefer path.deinit(gpa);
2061 .sub_file_path = sub_file_path,
20622287
2288 const file_gop = try zcu.import_table.getOrPutAdapted(gpa, path, Zcu.ImportTableAdapter{ .zcu = zcu });
2289 // `Compilation.Path.isIllegalZigImport` checks guard file creation, so
2290 // there isn't an `import_table` entry for this path yet.
2291 assert(!file_gop.found_existing);
2292 errdefer _ = zcu.import_table.pop();
2293
2294 try zcu.module_roots.ensureUnusedCapacity(gpa, 1);
2295
2296 const file = try gpa.create(Zcu.File);
2297 errdefer gpa.destroy(file);
2298
2299 file.* = .{
2063 .status = .never_loaded,2300 .status = .never_loaded,
2064 .stat = undefined,2301 .stat = undefined,
20652302 .path = path,
2303 .is_builtin = true,
2066 .source = null,2304 .source = null,
2067 .tree = null,2305 .tree = null,
2068 .zir = null,2306 .zir = null,
2069 .zoir = null,2307 .zoir = null,
2070
2071 .mod = mod,2308 .mod = mod,
2309 .sub_file_path = "builtin.zig",
2310 .module_changed = false,
2311 .prev_zir = null,
2312 .zoir_invalidated = false,
2072 };2313 };
20732314
2074 return .{2315 const file_index = try zcu.intern_pool.createFile(gpa, pt.tid, .{
2075 .file = new_file,2316 .bin_digest = path.digest(),
2076 .file_index = new_file_index,2317 .file = file,
2077 .is_new = true,2318 .root_type = .none,
2078 .is_pkg = false,2319 });
2079 };2320
2321 gop.value_ptr.* = mod;
2322 file_gop.key_ptr.* = file_index;
2323 zcu.module_roots.putAssumeCapacityNoClobber(mod, file_index.toOptional());
2324 try opts.populateFile(gpa, file);
2325
2326 assert(file.status == .success);
2327 assert(!file.zir.?.hasCompileErrors());
2328 {
2329 // Check that it has only one import, which is 'std'.
2330 const imports_idx = file.zir.?.extra[@intFromEnum(Zir.ExtraIndex.imports)];
2331 assert(imports_idx != 0); // there is an import
2332 const extra = file.zir.?.extraData(Zir.Inst.Imports, imports_idx);
2333 assert(extra.data.imports_len == 1); // there is exactly one import
2334 const item = file.zir.?.extraData(Zir.Inst.Imports.Item, extra.end);
2335 const import_path = file.zir.?.nullTerminatedString(item.data.name);
2336 assert(mem.eql(u8, import_path, "std")); // the single import is of 'std'
2337 }
2338
2339 Builtin.updateFileOnDisk(file, comp) catch |err| comp.setMiscFailure(
2340 .write_builtin_zig,
2341 "unable to write '{}': {s}",
2342 .{ file.path.fmt(comp), @errorName(err) },
2343 );
2080}2344}
20812345
2082pub fn embedFile(2346pub fn embedFile(
...@@ -2091,63 +2355,49 @@ pub fn embedFile(...@@ -2091,63 +2355,49 @@ pub fn embedFile(
2091 const zcu = pt.zcu;2355 const zcu = pt.zcu;
2092 const gpa = zcu.gpa;2356 const gpa = zcu.gpa;
20932357
2094 if (cur_file.mod.deps.get(import_string)) |mod| {2358 const opt_mod: ?*Module = m: {
2095 const resolved_path = try std.fs.path.resolve(gpa, &.{2359 if (mem.eql(u8, import_string, "std")) break :m zcu.std_mod;
2096 mod.root.root_dir.path orelse ".",2360 if (mem.eql(u8, import_string, "root")) break :m zcu.root_mod;
2097 mod.root.sub_path,2361 if (mem.eql(u8, import_string, "builtin")) {
2098 mod.root_src_path,2362 const opts = cur_file.mod.?.getBuiltinOptions(zcu.comp.config);
2099 });2363 break :m zcu.builtin_modules.get(opts.hash()).?;
2100 errdefer gpa.free(resolved_path);2364 }
21012365 break :m cur_file.mod.?.deps.get(import_string);
2102 const gop = try zcu.embed_table.getOrPut(gpa, resolved_path);2366 };
2103 errdefer assert(std.mem.eql(u8, zcu.embed_table.pop().?.key, resolved_path));2367 if (opt_mod) |mod| {
2368 const path = try mod.root.join(gpa, zcu.comp.dirs, mod.root_src_path);
2369 errdefer path.deinit(gpa);
21042370
2371 const gop = try zcu.embed_table.getOrPutAdapted(gpa, path, Zcu.EmbedTableAdapter{});
2105 if (gop.found_existing) {2372 if (gop.found_existing) {
2106 gpa.free(resolved_path); // we're not using this key2373 path.deinit(gpa); // we're not using this key
2107 return @enumFromInt(gop.index);2374 return @enumFromInt(gop.index);
2108 }2375 }
21092376 errdefer _ = zcu.embed_table.pop();
2110 gop.value_ptr.* = try pt.newEmbedFile(mod, mod.root_src_path, resolved_path);2377 gop.key_ptr.* = try pt.newEmbedFile(path);
2111 return @enumFromInt(gop.index);2378 return @enumFromInt(gop.index);
2112 }2379 }
21132380
2114 // The resolved path is used as the key in the table, to detect if a file2381 const embed_file: *Zcu.EmbedFile, const embed_file_idx: Zcu.EmbedFile.Index = ef: {
2115 // refers to the same as another, despite different relative paths.2382 const path = try cur_file.path.upJoin(gpa, zcu.comp.dirs, import_string);
2116 const resolved_path = try std.fs.path.resolve(gpa, &.{2383 errdefer path.deinit(gpa);
2117 cur_file.mod.root.root_dir.path orelse ".",2384 const gop = try zcu.embed_table.getOrPutAdapted(gpa, path, Zcu.EmbedTableAdapter{});
2118 cur_file.mod.root.sub_path,2385 if (gop.found_existing) {
2119 cur_file.sub_file_path,2386 path.deinit(gpa); // we're not using this key
2120 "..",2387 break :ef .{ gop.key_ptr.*, @enumFromInt(gop.index) };
2121 import_string,2388 } else {
2122 });2389 errdefer _ = zcu.embed_table.pop();
2123 errdefer gpa.free(resolved_path);2390 gop.key_ptr.* = try pt.newEmbedFile(path);
21242391 break :ef .{ gop.key_ptr.*, @enumFromInt(gop.index) };
2125 const gop = try zcu.embed_table.getOrPut(gpa, resolved_path);2392 }
2126 errdefer assert(std.mem.eql(u8, zcu.embed_table.pop().?.key, resolved_path));
2127
2128 if (gop.found_existing) {
2129 gpa.free(resolved_path); // we're not using this key
2130 return @enumFromInt(gop.index);
2131 }
2132
2133 const resolved_root_path = try std.fs.path.resolve(gpa, &.{
2134 cur_file.mod.root.root_dir.path orelse ".",
2135 cur_file.mod.root.sub_path,
2136 });
2137 defer gpa.free(resolved_root_path);
2138
2139 const sub_file_path = std.fs.path.relative(gpa, resolved_root_path, resolved_path) catch |err| switch (err) {
2140 error.Unexpected => unreachable,
2141 else => |e| return e,
2142 };2393 };
2143 defer gpa.free(sub_file_path);
21442394
2145 if (isUpDir(sub_file_path) or std.fs.path.isAbsolute(sub_file_path)) {2395 switch (embed_file.path.isNested(cur_file.mod.?.root)) {
2146 return error.ImportOutsideModulePath;2396 .yes => {},
2397 .different_roots, .no => return error.ImportOutsideModulePath,
2147 }2398 }
21482399
2149 gop.value_ptr.* = try pt.newEmbedFile(cur_file.mod, sub_file_path, resolved_path);2400 return embed_file_idx;
2150 return @enumFromInt(gop.index);
2151}2401}
21522402
2153pub fn updateEmbedFile(2403pub fn updateEmbedFile(
...@@ -2177,7 +2427,10 @@ fn updateEmbedFileInner(...@@ -2177,7 +2427,10 @@ fn updateEmbedFileInner(
2177 const gpa = zcu.gpa;2427 const gpa = zcu.gpa;
2178 const ip = &zcu.intern_pool;2428 const ip = &zcu.intern_pool;
21792429
2180 var file = try ef.owner.root.openFile(ef.sub_file_path.toSlice(ip), .{});2430 var file = f: {
2431 const dir, const sub_path = ef.path.openInfo(zcu.comp.dirs);
2432 break :f try dir.openFile(sub_path, .{});
2433 };
2181 defer file.close();2434 defer file.close();
21822435
2183 const stat: Cache.File.Stat = .fromFs(try file.stat());2436 const stat: Cache.File.Stat = .fromFs(try file.stat());
...@@ -2232,28 +2485,21 @@ fn updateEmbedFileInner(...@@ -2232,28 +2485,21 @@ fn updateEmbedFileInner(
2232 ef.stat = stat;2485 ef.stat = stat;
2233}2486}
22342487
2488/// Assumes that `path` is allocated into `gpa`. Takes ownership of `path` on success.
2235fn newEmbedFile(2489fn newEmbedFile(
2236 pt: Zcu.PerThread,2490 pt: Zcu.PerThread,
2237 mod: *Module,2491 path: Compilation.Path,
2238 /// The path of the file to embed relative to the root of `mod`.
2239 sub_file_path: []const u8,
2240 /// The resolved path of the file to embed.
2241 resolved_path: []const u8,
2242) !*Zcu.EmbedFile {2492) !*Zcu.EmbedFile {
2243 const zcu = pt.zcu;2493 const zcu = pt.zcu;
2244 const comp = zcu.comp;2494 const comp = zcu.comp;
2245 const gpa = zcu.gpa;2495 const gpa = zcu.gpa;
2246 const ip = &zcu.intern_pool;2496 const ip = &zcu.intern_pool;
22472497
2248 if (comp.file_system_inputs) |fsi|
2249 try comp.appendFileSystemInput(fsi, mod.root, sub_file_path);
2250
2251 const new_file = try gpa.create(Zcu.EmbedFile);2498 const new_file = try gpa.create(Zcu.EmbedFile);
2252 errdefer gpa.destroy(new_file);2499 errdefer gpa.destroy(new_file);
22532500
2254 new_file.* = .{2501 new_file.* = .{
2255 .owner = mod,2502 .path = path,
2256 .sub_file_path = try ip.getOrPutString(gpa, pt.tid, sub_file_path, .no_embedded_nulls),
2257 .val = .none,2503 .val = .none,
2258 .err = null,2504 .err = null,
2259 .stat = undefined,2505 .stat = undefined,
...@@ -2262,6 +2508,8 @@ fn newEmbedFile(...@@ -2262,6 +2508,8 @@ fn newEmbedFile(
2262 var opt_ip_str: ?InternPool.String = null;2508 var opt_ip_str: ?InternPool.String = null;
2263 try pt.updateEmbedFile(new_file, &opt_ip_str);2509 try pt.updateEmbedFile(new_file, &opt_ip_str);
22642510
2511 try comp.appendFileSystemInput(path);
2512
2265 // Add the file contents to the `whole` cache manifest if necessary.2513 // Add the file contents to the `whole` cache manifest if necessary.
2266 cache: {2514 cache: {
2267 const whole = switch (zcu.comp.cache_use) {2515 const whole = switch (zcu.comp.cache_use) {
...@@ -2269,17 +2517,18 @@ fn newEmbedFile(...@@ -2269,17 +2517,18 @@ fn newEmbedFile(
2269 .incremental => break :cache,2517 .incremental => break :cache,
2270 };2518 };
2271 const man = whole.cache_manifest orelse break :cache;2519 const man = whole.cache_manifest orelse break :cache;
2272 const ip_str = opt_ip_str orelse break :cache;2520 const ip_str = opt_ip_str orelse break :cache; // this will be a compile error
2273
2274 const copied_resolved_path = try gpa.dupe(u8, resolved_path);
2275 errdefer gpa.free(copied_resolved_path);
22762521
2277 const array_len = Value.fromInterned(new_file.val).typeOf(zcu).childType(zcu).arrayLen(zcu);2522 const array_len = Value.fromInterned(new_file.val).typeOf(zcu).childType(zcu).arrayLen(zcu);
2523 const contents = ip_str.toSlice(array_len, ip);
2524
2525 const path_str = try path.toAbsolute(comp.dirs, gpa);
2526 defer gpa.free(path_str);
22782527
2279 whole.cache_manifest_mutex.lock();2528 whole.cache_manifest_mutex.lock();
2280 defer whole.cache_manifest_mutex.unlock();2529 defer whole.cache_manifest_mutex.unlock();
22812530
2282 man.addFilePostContents(copied_resolved_path, ip_str.toSlice(array_len, ip), new_file.stat) catch |err| switch (err) {2531 man.addFilePostContents(path_str, contents, new_file.stat) catch |err| switch (err) {
2283 error.Unexpected => unreachable,2532 error.Unexpected => unreachable,
2284 else => |e| return e,2533 else => |e| return e,
2285 };2534 };
...@@ -2805,7 +3054,7 @@ pub fn getErrorValueFromSlice(pt: Zcu.PerThread, name: []const u8) Allocator.Err...@@ -2805,7 +3054,7 @@ pub fn getErrorValueFromSlice(pt: Zcu.PerThread, name: []const u8) Allocator.Err
28053054
2806/// Removes any entry from `Zcu.failed_files` associated with `file`. Acquires `Compilation.mutex` as needed.3055/// Removes any entry from `Zcu.failed_files` associated with `file`. Acquires `Compilation.mutex` as needed.
2807/// `file.zir` must be unchanged from the last update, as it is used to determine if there is such an entry.3056/// `file.zir` must be unchanged from the last update, as it is used to determine if there is such an entry.
2808fn lockAndClearFileCompileError(pt: Zcu.PerThread, file: *Zcu.File) void {3057fn lockAndClearFileCompileError(pt: Zcu.PerThread, file_index: Zcu.File.Index, file: *Zcu.File) void {
2809 const maybe_has_error = switch (file.status) {3058 const maybe_has_error = switch (file.status) {
2810 .never_loaded => false,3059 .never_loaded => false,
2811 .retryable_failure => true,3060 .retryable_failure => true,
...@@ -2829,9 +3078,9 @@ fn lockAndClearFileCompileError(pt: Zcu.PerThread, file: *Zcu.File) void {...@@ -2829,9 +3078,9 @@ fn lockAndClearFileCompileError(pt: Zcu.PerThread, file: *Zcu.File) void {
28293078
2830 pt.zcu.comp.mutex.lock();3079 pt.zcu.comp.mutex.lock();
2831 defer pt.zcu.comp.mutex.unlock();3080 defer pt.zcu.comp.mutex.unlock();
2832 if (pt.zcu.failed_files.fetchSwapRemove(file)) |kv| {3081 if (pt.zcu.failed_files.fetchSwapRemove(file_index)) |kv| {
2833 assert(maybe_has_error); // the runtime safety case above3082 assert(maybe_has_error); // the runtime safety case above
2834 if (kv.value) |msg| msg.destroy(pt.zcu.gpa); // delete previous error message3083 if (kv.value) |msg| pt.zcu.gpa.free(msg); // delete previous error message
2835 }3084 }
2836}3085}
28373086
...@@ -3009,8 +3258,8 @@ pub fn populateTestFunctions(...@@ -3009,8 +3258,8 @@ pub fn populateTestFunctions(
3009 const zcu = pt.zcu;3258 const zcu = pt.zcu;
3010 const gpa = zcu.gpa;3259 const gpa = zcu.gpa;
3011 const ip = &zcu.intern_pool;3260 const ip = &zcu.intern_pool;
3012 const builtin_mod = zcu.root_mod.getBuiltinDependency();3261 const builtin_mod = zcu.builtin_modules.get(zcu.root_mod.getBuiltinOptions(zcu.comp.config).hash()).?;
3013 const builtin_file_index = (pt.importPkg(builtin_mod) catch unreachable).file_index;3262 const builtin_file_index = zcu.module_roots.get(builtin_mod).?.unwrap().?;
3014 pt.ensureFileAnalyzed(builtin_file_index) catch |err| switch (err) {3263 pt.ensureFileAnalyzed(builtin_file_index) catch |err| switch (err) {
3015 error.AnalysisFail => unreachable, // builtin module is generated so cannot be corrupt3264 error.AnalysisFail => unreachable, // builtin module is generated so cannot be corrupt
3016 error.OutOfMemory => |e| return e,3265 error.OutOfMemory => |e| return e,
...@@ -3213,54 +3462,8 @@ pub fn linkerUpdateLineNumber(pt: Zcu.PerThread, ti: InternPool.TrackedInst.Inde...@@ -3213,54 +3462,8 @@ pub fn linkerUpdateLineNumber(pt: Zcu.PerThread, ti: InternPool.TrackedInst.Inde
3213 }3462 }
3214}3463}
32153464
3216/// Sets `File.status` of `file_index` to `retryable_failure`, and stores an error in `pt.zcu.failed_files`.3465/// Stores an error in `pt.zcu.failed_files` for this file, and sets the file
3217pub fn reportRetryableAstGenError(3466/// status to `retryable_failure`.
3218 pt: Zcu.PerThread,
3219 src: Zcu.AstGenSrc,
3220 file_index: Zcu.File.Index,
3221 err: anyerror,
3222) error{OutOfMemory}!void {
3223 const zcu = pt.zcu;
3224 const gpa = zcu.gpa;
3225 const ip = &zcu.intern_pool;
3226
3227 const file = zcu.fileByIndex(file_index);
3228 file.status = .retryable_failure;
3229
3230 const src_loc: Zcu.LazySrcLoc = switch (src) {
3231 .root => .{
3232 .base_node_inst = try ip.trackZir(gpa, pt.tid, .{
3233 .file = file_index,
3234 .inst = .main_struct_inst,
3235 }),
3236 .offset = .entire_file,
3237 },
3238 .import => |info| .{
3239 .base_node_inst = try ip.trackZir(gpa, pt.tid, .{
3240 .file = info.importing_file,
3241 .inst = .main_struct_inst,
3242 }),
3243 .offset = .{ .token_abs = info.import_tok },
3244 },
3245 };
3246
3247 const err_msg = try Zcu.ErrorMsg.create(gpa, src_loc, "unable to load '{}/{s}': {s}", .{
3248 file.mod.root, file.sub_file_path, @errorName(err),
3249 });
3250 errdefer err_msg.destroy(gpa);
3251
3252 zcu.comp.mutex.lock();
3253 defer zcu.comp.mutex.unlock();
3254 const gop = try zcu.failed_files.getOrPut(gpa, file);
3255 if (gop.found_existing) {
3256 if (gop.value_ptr.*) |old_err_msg| {
3257 old_err_msg.destroy(gpa);
3258 }
3259 }
3260 gop.value_ptr.* = err_msg;
3261}
3262
3263/// Sets `File.status` of `file_index` to `retryable_failure`, and stores an error in `pt.zcu.failed_files`.
3264pub fn reportRetryableFileError(3467pub fn reportRetryableFileError(
3265 pt: Zcu.PerThread,3468 pt: Zcu.PerThread,
3266 file_index: Zcu.File.Index,3469 file_index: Zcu.File.Index,
...@@ -3269,35 +3472,27 @@ pub fn reportRetryableFileError(...@@ -3269,35 +3472,27 @@ pub fn reportRetryableFileError(
3269) error{OutOfMemory}!void {3472) error{OutOfMemory}!void {
3270 const zcu = pt.zcu;3473 const zcu = pt.zcu;
3271 const gpa = zcu.gpa;3474 const gpa = zcu.gpa;
3272 const ip = &zcu.intern_pool;
32733475
3274 const file = zcu.fileByIndex(file_index);3476 const file = zcu.fileByIndex(file_index);
3477
3275 file.status = .retryable_failure;3478 file.status = .retryable_failure;
32763479
3277 const err_msg = try Zcu.ErrorMsg.create(3480 const msg = try std.fmt.allocPrint(gpa, format, args);
3278 gpa,3481 errdefer gpa.free(msg);
3279 .{
3280 .base_node_inst = try ip.trackZir(gpa, pt.tid, .{
3281 .file = file_index,
3282 .inst = .main_struct_inst,
3283 }),
3284 .offset = .entire_file,
3285 },
3286 format,
3287 args,
3288 );
3289 errdefer err_msg.destroy(gpa);
32903482
3291 zcu.comp.mutex.lock();3483 const old_msg: ?[]u8 = old_msg: {
3292 defer zcu.comp.mutex.unlock();3484 zcu.comp.mutex.lock();
3485 defer zcu.comp.mutex.unlock();
32933486
3294 const gop = try zcu.failed_files.getOrPut(gpa, file);3487 const gop = try zcu.failed_files.getOrPut(gpa, file_index);
3295 if (gop.found_existing) {3488 const old: ?[]u8 = if (gop.found_existing) old: {
3296 if (gop.value_ptr.*) |old_err_msg| {3489 break :old gop.value_ptr.*;
3297 old_err_msg.destroy(gpa);3490 } else null;
3298 }3491 gop.value_ptr.* = msg;
3299 }3492
3300 gop.value_ptr.* = err_msg;3493 break :old_msg old;
3494 };
3495 if (old_msg) |m| gpa.free(m);
3301}3496}
33023497
3303/// Shortcut for calling `intern_pool.get`.3498/// Shortcut for calling `intern_pool.get`.
...@@ -3850,7 +4045,7 @@ fn recreateStructType(...@@ -3850,7 +4045,7 @@ fn recreateStructType(
38504045
3851 codegen_type: {4046 codegen_type: {
3852 if (zcu.comp.config.use_llvm) break :codegen_type;4047 if (zcu.comp.config.use_llvm) break :codegen_type;
3853 if (file.mod.strip) break :codegen_type;4048 if (file.mod.?.strip) break :codegen_type;
3854 // This job depends on any resolve_type_fully jobs queued up before it.4049 // This job depends on any resolve_type_fully jobs queued up before it.
3855 try zcu.comp.queueJob(.{ .codegen_type = wip_ty.index });4050 try zcu.comp.queueJob(.{ .codegen_type = wip_ty.index });
3856 }4051 }
...@@ -3946,7 +4141,7 @@ fn recreateUnionType(...@@ -3946,7 +4141,7 @@ fn recreateUnionType(
39464141
3947 codegen_type: {4142 codegen_type: {
3948 if (zcu.comp.config.use_llvm) break :codegen_type;4143 if (zcu.comp.config.use_llvm) break :codegen_type;
3949 if (file.mod.strip) break :codegen_type;4144 if (file.mod.?.strip) break :codegen_type;
3950 // This job depends on any resolve_type_fully jobs queued up before it.4145 // This job depends on any resolve_type_fully jobs queued up before it.
3951 try zcu.comp.queueJob(.{ .codegen_type = wip_ty.index });4146 try zcu.comp.queueJob(.{ .codegen_type = wip_ty.index });
3952 }4147 }
src/arch/aarch64/CodeGen.zig+1-1
...@@ -333,7 +333,7 @@ pub fn generate(...@@ -333,7 +333,7 @@ pub fn generate(
333 const func = zcu.funcInfo(func_index);333 const func = zcu.funcInfo(func_index);
334 const fn_type = Type.fromInterned(func.ty);334 const fn_type = Type.fromInterned(func.ty);
335 const file_scope = zcu.navFileScope(func.owner_nav);335 const file_scope = zcu.navFileScope(func.owner_nav);
336 const target = &file_scope.mod.resolved_target.result;336 const target = &file_scope.mod.?.resolved_target.result;
337337
338 var branch_stack = std.ArrayList(Branch).init(gpa);338 var branch_stack = std.ArrayList(Branch).init(gpa);
339 defer {339 defer {
src/arch/arm/CodeGen.zig+1-1
...@@ -342,7 +342,7 @@ pub fn generate(...@@ -342,7 +342,7 @@ pub fn generate(
342 const func = zcu.funcInfo(func_index);342 const func = zcu.funcInfo(func_index);
343 const func_ty = Type.fromInterned(func.ty);343 const func_ty = Type.fromInterned(func.ty);
344 const file_scope = zcu.navFileScope(func.owner_nav);344 const file_scope = zcu.navFileScope(func.owner_nav);
345 const target = &file_scope.mod.resolved_target.result;345 const target = &file_scope.mod.?.resolved_target.result;
346346
347 var branch_stack = std.ArrayList(Branch).init(gpa);347 var branch_stack = std.ArrayList(Branch).init(gpa);
348 defer {348 defer {
src/arch/riscv64/CodeGen.zig+1-1
...@@ -767,7 +767,7 @@ pub fn generate(...@@ -767,7 +767,7 @@ pub fn generate(
767 const ip = &zcu.intern_pool;767 const ip = &zcu.intern_pool;
768 const func = zcu.funcInfo(func_index);768 const func = zcu.funcInfo(func_index);
769 const fn_type = Type.fromInterned(func.ty);769 const fn_type = Type.fromInterned(func.ty);
770 const mod = zcu.navFileScope(func.owner_nav).mod;770 const mod = zcu.navFileScope(func.owner_nav).mod.?;
771771
772 var branch_stack = std.ArrayList(Branch).init(gpa);772 var branch_stack = std.ArrayList(Branch).init(gpa);
773 defer {773 defer {
src/arch/sparc64/CodeGen.zig+1-1
...@@ -275,7 +275,7 @@ pub fn generate(...@@ -275,7 +275,7 @@ pub fn generate(
275 const func = zcu.funcInfo(func_index);275 const func = zcu.funcInfo(func_index);
276 const func_ty = Type.fromInterned(func.ty);276 const func_ty = Type.fromInterned(func.ty);
277 const file_scope = zcu.navFileScope(func.owner_nav);277 const file_scope = zcu.navFileScope(func.owner_nav);
278 const target = &file_scope.mod.resolved_target.result;278 const target = &file_scope.mod.?.resolved_target.result;
279279
280 var branch_stack = std.ArrayList(Branch).init(gpa);280 var branch_stack = std.ArrayList(Branch).init(gpa);
281 defer {281 defer {
src/arch/wasm/CodeGen.zig+1-1
...@@ -1268,7 +1268,7 @@ pub fn function(...@@ -1268,7 +1268,7 @@ pub fn function(
1268 const gpa = zcu.gpa;1268 const gpa = zcu.gpa;
1269 const cg = zcu.funcInfo(func_index);1269 const cg = zcu.funcInfo(func_index);
1270 const file_scope = zcu.navFileScope(cg.owner_nav);1270 const file_scope = zcu.navFileScope(cg.owner_nav);
1271 const target = &file_scope.mod.resolved_target.result;1271 const target = &file_scope.mod.?.resolved_target.result;
1272 const fn_ty = zcu.navValue(cg.owner_nav).typeOf(zcu);1272 const fn_ty = zcu.navValue(cg.owner_nav).typeOf(zcu);
1273 const fn_info = zcu.typeToFunc(fn_ty).?;1273 const fn_info = zcu.typeToFunc(fn_ty).?;
1274 const ip = &zcu.intern_pool;1274 const ip = &zcu.intern_pool;
src/arch/x86_64/CodeGen.zig+1-1
...@@ -888,7 +888,7 @@ pub fn generate(...@@ -888,7 +888,7 @@ pub fn generate(
888 const ip = &zcu.intern_pool;888 const ip = &zcu.intern_pool;
889 const func = zcu.funcInfo(func_index);889 const func = zcu.funcInfo(func_index);
890 const fn_type: Type = .fromInterned(func.ty);890 const fn_type: Type = .fromInterned(func.ty);
891 const mod = zcu.navFileScope(func.owner_nav).mod;891 const mod = zcu.navFileScope(func.owner_nav).mod.?;
892892
893 var function: CodeGen = .{893 var function: CodeGen = .{
894 .gpa = gpa,894 .gpa = gpa,
src/codegen.zig+4-4
...@@ -56,7 +56,7 @@ pub fn generateFunction(...@@ -56,7 +56,7 @@ pub fn generateFunction(
56) CodeGenError!void {56) CodeGenError!void {
57 const zcu = pt.zcu;57 const zcu = pt.zcu;
58 const func = zcu.funcInfo(func_index);58 const func = zcu.funcInfo(func_index);
59 const target = zcu.navFileScope(func.owner_nav).mod.resolved_target.result;59 const target = zcu.navFileScope(func.owner_nav).mod.?.resolved_target.result;
60 switch (target_util.zigBackend(target, false)) {60 switch (target_util.zigBackend(target, false)) {
61 else => unreachable,61 else => unreachable,
62 inline .stage2_aarch64,62 inline .stage2_aarch64,
...@@ -81,7 +81,7 @@ pub fn generateLazyFunction(...@@ -81,7 +81,7 @@ pub fn generateLazyFunction(
81) CodeGenError!void {81) CodeGenError!void {
82 const zcu = pt.zcu;82 const zcu = pt.zcu;
83 const target = if (Type.fromInterned(lazy_sym.ty).typeDeclInstAllowGeneratedTag(zcu)) |inst_index|83 const target = if (Type.fromInterned(lazy_sym.ty).typeDeclInstAllowGeneratedTag(zcu)) |inst_index|
84 zcu.fileByIndex(inst_index.resolveFile(&zcu.intern_pool)).mod.resolved_target.result84 zcu.fileByIndex(inst_index.resolveFile(&zcu.intern_pool)).mod.?.resolved_target.result
85 else85 else
86 zcu.getTarget();86 zcu.getTarget();
87 switch (target_util.zigBackend(target, false)) {87 switch (target_util.zigBackend(target, false)) {
...@@ -722,7 +722,7 @@ fn lowerNavRef(...@@ -722,7 +722,7 @@ fn lowerNavRef(
722 const zcu = pt.zcu;722 const zcu = pt.zcu;
723 const gpa = zcu.gpa;723 const gpa = zcu.gpa;
724 const ip = &zcu.intern_pool;724 const ip = &zcu.intern_pool;
725 const target = zcu.navFileScope(nav_index).mod.resolved_target.result;725 const target = zcu.navFileScope(nav_index).mod.?.resolved_target.result;
726 const ptr_width_bytes = @divExact(target.ptrBitWidth(), 8);726 const ptr_width_bytes = @divExact(target.ptrBitWidth(), 8);
727 const is_obj = lf.comp.config.output_mode == .Obj;727 const is_obj = lf.comp.config.output_mode == .Obj;
728 const nav_ty = Type.fromInterned(ip.getNav(nav_index).typeOf(ip));728 const nav_ty = Type.fromInterned(ip.getNav(nav_index).typeOf(ip));
...@@ -884,7 +884,7 @@ fn genNavRef(...@@ -884,7 +884,7 @@ fn genNavRef(
884 else884 else
885 .{ false, .none, nav.isThreadlocal(ip) };885 .{ false, .none, nav.isThreadlocal(ip) };
886886
887 const single_threaded = zcu.navFileScope(nav_index).mod.single_threaded;887 const single_threaded = zcu.navFileScope(nav_index).mod.?.single_threaded;
888 const name = nav.name;888 const name = nav.name;
889 if (lf.cast(.elf)) |elf_file| {889 if (lf.cast(.elf)) |elf_file| {
890 const zo = elf_file.zigObjectPtr().?;890 const zo = elf_file.zigObjectPtr().?;
src/codegen/c.zig+1-1
...@@ -2670,7 +2670,7 @@ pub fn genTypeDecl(...@@ -2670,7 +2670,7 @@ pub fn genTypeDecl(
2670 _ = try renderTypePrefix(.flush, global_ctype_pool, zcu, writer, global_ctype, .suffix, .{});2670 _ = try renderTypePrefix(.flush, global_ctype_pool, zcu, writer, global_ctype, .suffix, .{});
2671 try writer.writeByte(';');2671 try writer.writeByte(';');
2672 const file_scope = ty.typeDeclInstAllowGeneratedTag(zcu).?.resolveFile(ip);2672 const file_scope = ty.typeDeclInstAllowGeneratedTag(zcu).?.resolveFile(ip);
2673 if (!zcu.fileByIndex(file_scope).mod.strip) try writer.print(" /* {} */", .{2673 if (!zcu.fileByIndex(file_scope).mod.?.strip) try writer.print(" /* {} */", .{
2674 ty.containerTypeName(ip).fmt(ip),2674 ty.containerTypeName(ip).fmt(ip),
2675 });2675 });
2676 try writer.writeByte('\n');2676 try writer.writeByte('\n');
src/codegen/llvm.zig+17-30
...@@ -587,13 +587,8 @@ pub const Object = struct {...@@ -587,13 +587,8 @@ pub const Object = struct {
587 // into the garbage can by converting into absolute paths. What587 // into the garbage can by converting into absolute paths. What
588 // a terrible tragedy.588 // a terrible tragedy.
589 const compile_unit_dir = blk: {589 const compile_unit_dir = blk: {
590 if (comp.zcu) |zcu| m: {590 const zcu = comp.zcu orelse break :blk comp.dirs.cwd;
591 const d = try zcu.main_mod.root.joinString(arena, "");591 break :blk try zcu.main_mod.root.toAbsolute(comp.dirs, arena);
592 if (d.len == 0) break :m;
593 if (std.fs.path.isAbsolute(d)) break :blk d;
594 break :blk std.fs.realpathAlloc(arena, d) catch break :blk d;
595 }
596 break :blk try std.process.getCwdAlloc(arena);
597 };592 };
598593
599 const debug_file = try builder.debugFile(594 const debug_file = try builder.debugFile(
...@@ -1135,7 +1130,7 @@ pub const Object = struct {...@@ -1135,7 +1130,7 @@ pub const Object = struct {
1135 const func = zcu.funcInfo(func_index);1130 const func = zcu.funcInfo(func_index);
1136 const nav = ip.getNav(func.owner_nav);1131 const nav = ip.getNav(func.owner_nav);
1137 const file_scope = zcu.navFileScopeIndex(func.owner_nav);1132 const file_scope = zcu.navFileScopeIndex(func.owner_nav);
1138 const owner_mod = zcu.fileByIndex(file_scope).mod;1133 const owner_mod = zcu.fileByIndex(file_scope).mod.?;
1139 const fn_ty = Type.fromInterned(func.ty);1134 const fn_ty = Type.fromInterned(func.ty);
1140 const fn_info = zcu.typeToFunc(fn_ty).?;1135 const fn_info = zcu.typeToFunc(fn_ty).?;
1141 const target = owner_mod.resolved_target.result;1136 const target = owner_mod.resolved_target.result;
...@@ -1735,20 +1730,14 @@ pub const Object = struct {...@@ -1735,20 +1730,14 @@ pub const Object = struct {
1735 const gop = try o.debug_file_map.getOrPut(gpa, file_index);1730 const gop = try o.debug_file_map.getOrPut(gpa, file_index);
1736 errdefer assert(o.debug_file_map.remove(file_index));1731 errdefer assert(o.debug_file_map.remove(file_index));
1737 if (gop.found_existing) return gop.value_ptr.*;1732 if (gop.found_existing) return gop.value_ptr.*;
1738 const file = o.pt.zcu.fileByIndex(file_index);1733 const zcu = o.pt.zcu;
1734 const path = zcu.fileByIndex(file_index).path;
1735 const abs_path = try path.toAbsolute(zcu.comp.dirs, gpa);
1736 defer gpa.free(abs_path);
1737
1739 gop.value_ptr.* = try o.builder.debugFile(1738 gop.value_ptr.* = try o.builder.debugFile(
1740 try o.builder.metadataString(std.fs.path.basename(file.sub_file_path)),1739 try o.builder.metadataString(std.fs.path.basename(abs_path)),
1741 dir_path: {1740 try o.builder.metadataString(std.fs.path.dirname(abs_path) orelse ""),
1742 const sub_path = std.fs.path.dirname(file.sub_file_path) orelse "";
1743 const dir_path = try file.mod.root.joinString(gpa, sub_path);
1744 defer gpa.free(dir_path);
1745 if (std.fs.path.isAbsolute(dir_path))
1746 break :dir_path try o.builder.metadataString(dir_path);
1747 var abs_buffer: [std.fs.max_path_bytes]u8 = undefined;
1748 const abs_path = std.fs.realpath(dir_path, &abs_buffer) catch
1749 break :dir_path try o.builder.metadataString(dir_path);
1750 break :dir_path try o.builder.metadataString(abs_path);
1751 },
1752 );1741 );
1753 return gop.value_ptr.*;1742 return gop.value_ptr.*;
1754 }1743 }
...@@ -2646,11 +2635,9 @@ pub const Object = struct {...@@ -2646,11 +2635,9 @@ pub const Object = struct {
2646 const zcu = pt.zcu;2635 const zcu = pt.zcu;
2647 const ip = &zcu.intern_pool;2636 const ip = &zcu.intern_pool;
26482637
2649 const std_mod = zcu.std_mod;2638 const std_file_index = zcu.module_roots.get(zcu.std_mod).?.unwrap().?;
2650 const std_file_imported = pt.importPkg(std_mod) catch unreachable;
2651
2652 const builtin_str = try ip.getOrPutString(zcu.gpa, pt.tid, "builtin", .no_embedded_nulls);2639 const builtin_str = try ip.getOrPutString(zcu.gpa, pt.tid, "builtin", .no_embedded_nulls);
2653 const std_file_root_type = Type.fromInterned(zcu.fileRootType(std_file_imported.file_index));2640 const std_file_root_type = Type.fromInterned(zcu.fileRootType(std_file_index));
2654 const std_namespace = ip.namespacePtr(std_file_root_type.getNamespaceIndex(zcu));2641 const std_namespace = ip.namespacePtr(std_file_root_type.getNamespaceIndex(zcu));
2655 const builtin_nav = std_namespace.pub_decls.getKeyAdapted(builtin_str, Zcu.Namespace.NameAdapter{ .zcu = zcu }).?;2642 const builtin_nav = std_namespace.pub_decls.getKeyAdapted(builtin_str, Zcu.Namespace.NameAdapter{ .zcu = zcu }).?;
26562643
...@@ -2683,7 +2670,7 @@ pub const Object = struct {...@@ -2683,7 +2670,7 @@ pub const Object = struct {
2683 const ip = &zcu.intern_pool;2670 const ip = &zcu.intern_pool;
2684 const gpa = o.gpa;2671 const gpa = o.gpa;
2685 const nav = ip.getNav(nav_index);2672 const nav = ip.getNav(nav_index);
2686 const owner_mod = zcu.navFileScope(nav_index).mod;2673 const owner_mod = zcu.navFileScope(nav_index).mod.?;
2687 const ty: Type = .fromInterned(nav.typeOf(ip));2674 const ty: Type = .fromInterned(nav.typeOf(ip));
2688 const gop = try o.nav_map.getOrPut(gpa, nav_index);2675 const gop = try o.nav_map.getOrPut(gpa, nav_index);
2689 if (gop.found_existing) return gop.value_ptr.ptr(&o.builder).kind.function;2676 if (gop.found_existing) return gop.value_ptr.ptr(&o.builder).kind.function;
...@@ -3013,7 +3000,7 @@ pub const Object = struct {...@@ -3013,7 +3000,7 @@ pub const Object = struct {
3013 if (is_extern) {3000 if (is_extern) {
3014 variable_index.setLinkage(.external, &o.builder);3001 variable_index.setLinkage(.external, &o.builder);
3015 variable_index.setUnnamedAddr(.default, &o.builder);3002 variable_index.setUnnamedAddr(.default, &o.builder);
3016 if (is_threadlocal and !zcu.navFileScope(nav_index).mod.single_threaded)3003 if (is_threadlocal and !zcu.navFileScope(nav_index).mod.?.single_threaded)
3017 variable_index.setThreadLocal(.generaldynamic, &o.builder);3004 variable_index.setThreadLocal(.generaldynamic, &o.builder);
3018 if (is_weak_linkage) variable_index.setLinkage(.extern_weak, &o.builder);3005 if (is_weak_linkage) variable_index.setLinkage(.extern_weak, &o.builder);
3019 if (is_dll_import) variable_index.setDllStorageClass(.dllimport, &o.builder);3006 if (is_dll_import) variable_index.setDllStorageClass(.dllimport, &o.builder);
...@@ -4514,7 +4501,7 @@ pub const NavGen = struct {...@@ -4514,7 +4501,7 @@ pub const NavGen = struct {
4514 err_msg: ?*Zcu.ErrorMsg,4501 err_msg: ?*Zcu.ErrorMsg,
45154502
4516 fn ownerModule(ng: NavGen) *Package.Module {4503 fn ownerModule(ng: NavGen) *Package.Module {
4517 return ng.object.pt.zcu.navFileScope(ng.nav_index).mod;4504 return ng.object.pt.zcu.navFileScope(ng.nav_index).mod.?;
4518 }4505 }
45194506
4520 fn todo(ng: *NavGen, comptime format: []const u8, args: anytype) Error {4507 fn todo(ng: *NavGen, comptime format: []const u8, args: anytype) Error {
...@@ -4557,7 +4544,7 @@ pub const NavGen = struct {...@@ -4557,7 +4544,7 @@ pub const NavGen = struct {
4557 }, &o.builder);4544 }, &o.builder);
45584545
4559 const file_scope = zcu.navFileScopeIndex(nav_index);4546 const file_scope = zcu.navFileScopeIndex(nav_index);
4560 const mod = zcu.fileByIndex(file_scope).mod;4547 const mod = zcu.fileByIndex(file_scope).mod.?;
4561 if (is_threadlocal and !mod.single_threaded)4548 if (is_threadlocal and !mod.single_threaded)
4562 variable_index.setThreadLocal(.generaldynamic, &o.builder);4549 variable_index.setThreadLocal(.generaldynamic, &o.builder);
45634550
...@@ -5121,7 +5108,7 @@ pub const FuncGen = struct {...@@ -5121,7 +5108,7 @@ pub const FuncGen = struct {
5121 const func = zcu.funcInfo(inline_func);5108 const func = zcu.funcInfo(inline_func);
5122 const nav = ip.getNav(func.owner_nav);5109 const nav = ip.getNav(func.owner_nav);
5123 const file_scope = zcu.navFileScopeIndex(func.owner_nav);5110 const file_scope = zcu.navFileScopeIndex(func.owner_nav);
5124 const mod = zcu.fileByIndex(file_scope).mod;5111 const mod = zcu.fileByIndex(file_scope).mod.?;
51255112
5126 self.file = try o.getDebugFile(file_scope);5113 self.file = try o.getDebugFile(file_scope);
51275114
src/codegen/spirv.zig+1-1
...@@ -201,7 +201,7 @@ pub const Object = struct {...@@ -201,7 +201,7 @@ pub const Object = struct {
201 ) !void {201 ) !void {
202 const zcu = pt.zcu;202 const zcu = pt.zcu;
203 const gpa = zcu.gpa;203 const gpa = zcu.gpa;
204 const structured_cfg = zcu.navFileScope(nav_index).mod.structured_cfg;204 const structured_cfg = zcu.navFileScope(nav_index).mod.?.structured_cfg;
205205
206 var nav_gen = NavGen{206 var nav_gen = NavGen{
207 .gpa = gpa,207 .gpa = gpa,
src/crash_report.zig+13-27
...@@ -86,15 +86,12 @@ fn dumpStatusReport() !void {...@@ -86,15 +86,12 @@ fn dumpStatusReport() !void {
8686
87 const file, const src_base_node = Zcu.LazySrcLoc.resolveBaseNode(block.src_base_inst, zcu) orelse {87 const file, const src_base_node = Zcu.LazySrcLoc.resolveBaseNode(block.src_base_inst, zcu) orelse {
88 const file = zcu.fileByIndex(block.src_base_inst.resolveFile(&zcu.intern_pool));88 const file = zcu.fileByIndex(block.src_base_inst.resolveFile(&zcu.intern_pool));
89 try stderr.writeAll("Analyzing lost instruction in file '");89 try stderr.print("Analyzing lost instruction in file '{}'. This should not happen!\n\n", .{file.path.fmt(zcu.comp)});
90 try writeFilePath(file, stderr);
91 try stderr.writeAll("'. This should not happen!\n\n");
92 return;90 return;
93 };91 };
9492
95 try stderr.writeAll("Analyzing ");93 try stderr.writeAll("Analyzing ");
96 try writeFilePath(file, stderr);94 try stderr.print("Analyzing '{}'\n", .{file.path.fmt(zcu.comp)});
97 try stderr.writeAll("\n");
9895
99 print_zir.renderInstructionContext(96 print_zir.renderInstructionContext(
100 allocator,97 allocator,
...@@ -108,23 +105,24 @@ fn dumpStatusReport() !void {...@@ -108,23 +105,24 @@ fn dumpStatusReport() !void {
108 error.OutOfMemory => try stderr.writeAll(" <out of memory dumping zir>\n"),105 error.OutOfMemory => try stderr.writeAll(" <out of memory dumping zir>\n"),
109 else => |e| return e,106 else => |e| return e,
110 };107 };
111 try stderr.writeAll(" For full context, use the command\n zig ast-check -t ");108 try stderr.print(
112 try writeFilePath(file, stderr);109 \\ For full context, use the command
113 try stderr.writeAll("\n\n");110 \\ zig ast-check -t {}
111 \\
112 \\
113 , .{file.path.fmt(zcu.comp)});
114114
115 var parent = anal.parent;115 var parent = anal.parent;
116 while (parent) |curr| {116 while (parent) |curr| {
117 fba.reset();117 fba.reset();
118 try stderr.writeAll(" in ");118 const cur_block_file = zcu.fileByIndex(curr.block.src_base_inst.resolveFile(&zcu.intern_pool));
119 const cur_block_file, const cur_block_src_base_node = Zcu.LazySrcLoc.resolveBaseNode(curr.block.src_base_inst, zcu) orelse {119 try stderr.print(" in {}\n", .{cur_block_file.path.fmt(zcu.comp)});
120 const cur_block_file = zcu.fileByIndex(curr.block.src_base_inst.resolveFile(&zcu.intern_pool));120 _, const cur_block_src_base_node = Zcu.LazySrcLoc.resolveBaseNode(curr.block.src_base_inst, zcu) orelse {
121 try writeFilePath(cur_block_file, stderr);121 try stderr.writeAll(" > [lost instruction; this should not happen]\n");
122 try stderr.writeAll("\n > [lost instruction; this should not happen]\n");
123 parent = curr.parent;122 parent = curr.parent;
124 continue;123 continue;
125 };124 };
126 try writeFilePath(cur_block_file, stderr);125 try stderr.writeAll(" > ");
127 try stderr.writeAll("\n > ");
128 print_zir.renderSingleInstruction(126 print_zir.renderSingleInstruction(
129 allocator,127 allocator,
130 curr.body[curr.body_index],128 curr.body[curr.body_index],
...@@ -146,18 +144,6 @@ fn dumpStatusReport() !void {...@@ -146,18 +144,6 @@ fn dumpStatusReport() !void {
146144
147var crash_heap: [16 * 4096]u8 = undefined;145var crash_heap: [16 * 4096]u8 = undefined;
148146
149fn writeFilePath(file: *Zcu.File, writer: anytype) !void {
150 if (file.mod.root.root_dir.path) |path| {
151 try writer.writeAll(path);
152 try writer.writeAll(std.fs.path.sep_str);
153 }
154 if (file.mod.root.sub_path.len > 0) {
155 try writer.writeAll(file.mod.root.sub_path);
156 try writer.writeAll(std.fs.path.sep_str);
157 }
158 try writer.writeAll(file.sub_file_path);
159}
160
161pub fn compilerPanic(msg: []const u8, maybe_ret_addr: ?usize) noreturn {147pub fn compilerPanic(msg: []const u8, maybe_ret_addr: ?usize) noreturn {
162 @branchHint(.cold);148 @branchHint(.cold);
163 PanicSwitch.preDispatch();149 PanicSwitch.preDispatch();
src/introspect.zig+129-60
...@@ -1,15 +1,18 @@...@@ -1,15 +1,18 @@
1const std = @import("std");1const std = @import("std");
2const builtin = @import("builtin");2const builtin = @import("builtin");
3const mem = std.mem;3const mem = std.mem;
4const Allocator = mem.Allocator;
4const os = std.os;5const os = std.os;
5const fs = std.fs;6const fs = std.fs;
7const Cache = std.Build.Cache;
6const Compilation = @import("Compilation.zig");8const Compilation = @import("Compilation.zig");
9const Package = @import("Package.zig");
7const build_options = @import("build_options");10const build_options = @import("build_options");
811
9/// Returns the sub_path that worked, or `null` if none did.12/// Returns the sub_path that worked, or `null` if none did.
10/// The path of the returned Directory is relative to `base`.13/// The path of the returned Directory is relative to `base`.
11/// The handle of the returned Directory is open.14/// The handle of the returned Directory is open.
12fn testZigInstallPrefix(base_dir: fs.Dir) ?Compilation.Directory {15fn testZigInstallPrefix(base_dir: fs.Dir) ?Cache.Directory {
13 const test_index_file = "std" ++ fs.path.sep_str ++ "std.zig";16 const test_index_file = "std" ++ fs.path.sep_str ++ "std.zig";
1417
15 zig_dir: {18 zig_dir: {
...@@ -21,7 +24,7 @@ fn testZigInstallPrefix(base_dir: fs.Dir) ?Compilation.Directory {...@@ -21,7 +24,7 @@ fn testZigInstallPrefix(base_dir: fs.Dir) ?Compilation.Directory {
21 break :zig_dir;24 break :zig_dir;
22 };25 };
23 file.close();26 file.close();
24 return Compilation.Directory{ .handle = test_zig_dir, .path = lib_zig };27 return .{ .handle = test_zig_dir, .path = lib_zig };
25 }28 }
2629
27 // Try lib/std/std.zig30 // Try lib/std/std.zig
...@@ -31,37 +34,50 @@ fn testZigInstallPrefix(base_dir: fs.Dir) ?Compilation.Directory {...@@ -31,37 +34,50 @@ fn testZigInstallPrefix(base_dir: fs.Dir) ?Compilation.Directory {
31 return null;34 return null;
32 };35 };
33 file.close();36 file.close();
34 return Compilation.Directory{ .handle = test_zig_dir, .path = "lib" };37 return .{ .handle = test_zig_dir, .path = "lib" };
35}
36
37/// This is a small wrapper around selfExePathAlloc that adds support for WASI
38/// based on a hard-coded Preopen directory ("/zig")
39pub fn findZigExePath(allocator: mem.Allocator) ![]u8 {
40 if (builtin.os.tag == .wasi) {
41 @compileError("this function is unsupported on WASI");
42 }
43
44 return fs.selfExePathAlloc(allocator);
45}38}
4639
47/// Both the directory handle and the path are newly allocated resources which the caller now owns.40/// Both the directory handle and the path are newly allocated resources which the caller now owns.
48pub fn findZigLibDir(gpa: mem.Allocator) !Compilation.Directory {41pub fn findZigLibDir(gpa: Allocator) !Cache.Directory {
49 const self_exe_path = try findZigExePath(gpa);42 const cwd_path = try getResolvedCwd(gpa);
43 defer gpa.free(cwd_path);
44 const self_exe_path = try fs.selfExePathAlloc(gpa);
50 defer gpa.free(self_exe_path);45 defer gpa.free(self_exe_path);
5146
52 return findZigLibDirFromSelfExe(gpa, self_exe_path);47 return findZigLibDirFromSelfExe(gpa, cwd_path, self_exe_path);
53}48}
5449
55/// Both the directory handle and the path are newly allocated resources which the caller now owns.50/// Like `std.process.getCwdAlloc`, but also resolves the path with `std.fs.path.resolve`. This
56pub fn findZigLibDirFromSelfExe(51/// means the path has no repeated separators, no "." or ".." components, and no trailing separator.
57 allocator: mem.Allocator,52/// On WASI, "" is returned instead of ".".
58 self_exe_path: []const u8,53pub fn getResolvedCwd(gpa: Allocator) error{
59) error{
60 OutOfMemory,54 OutOfMemory,
61 FileNotFound,
62 CurrentWorkingDirectoryUnlinked,55 CurrentWorkingDirectoryUnlinked,
63 Unexpected,56 Unexpected,
64}!Compilation.Directory {57}![]u8 {
58 if (builtin.target.os.tag == .wasi) {
59 if (std.debug.runtime_safety) {
60 const cwd = try std.process.getCwdAlloc(gpa);
61 defer gpa.free(cwd);
62 std.debug.assert(mem.eql(u8, cwd, "."));
63 }
64 return "";
65 }
66 const cwd = try std.process.getCwdAlloc(gpa);
67 defer gpa.free(cwd);
68 const resolved = try fs.path.resolve(gpa, &.{cwd});
69 std.debug.assert(fs.path.isAbsolute(resolved));
70 return resolved;
71}
72
73/// Both the directory handle and the path are newly allocated resources which the caller now owns.
74pub fn findZigLibDirFromSelfExe(
75 allocator: Allocator,
76 /// The return value of `getResolvedCwd`.
77 /// Passed as an argument to avoid pointlessly repeating the call.
78 cwd_path: []const u8,
79 self_exe_path: []const u8,
80) error{ OutOfMemory, FileNotFound }!Cache.Directory {
65 const cwd = fs.cwd();81 const cwd = fs.cwd();
66 var cur_path: []const u8 = self_exe_path;82 var cur_path: []const u8 = self_exe_path;
67 while (fs.path.dirname(cur_path)) |dirname| : (cur_path = dirname) {83 while (fs.path.dirname(cur_path)) |dirname| : (cur_path = dirname) {
...@@ -69,18 +85,20 @@ pub fn findZigLibDirFromSelfExe(...@@ -69,18 +85,20 @@ pub fn findZigLibDirFromSelfExe(
69 defer base_dir.close();85 defer base_dir.close();
7086
71 const sub_directory = testZigInstallPrefix(base_dir) orelse continue;87 const sub_directory = testZigInstallPrefix(base_dir) orelse continue;
72 const p = try fs.path.join(allocator, &[_][]const u8{ dirname, sub_directory.path.? });88 const p = try fs.path.join(allocator, &.{ dirname, sub_directory.path.? });
73 defer allocator.free(p);89 defer allocator.free(p);
74 return Compilation.Directory{90
91 const resolved = try resolvePath(allocator, cwd_path, &.{p});
92 return .{
75 .handle = sub_directory.handle,93 .handle = sub_directory.handle,
76 .path = try resolvePath(allocator, p),94 .path = if (resolved.len == 0) null else resolved,
77 };95 };
78 }96 }
79 return error.FileNotFound;97 return error.FileNotFound;
80}98}
8199
82/// Caller owns returned memory.100/// Caller owns returned memory.
83pub fn resolveGlobalCacheDir(allocator: mem.Allocator) ![]u8 {101pub fn resolveGlobalCacheDir(allocator: Allocator) ![]u8 {
84 if (builtin.os.tag == .wasi)102 if (builtin.os.tag == .wasi)
85 @compileError("on WASI the global cache dir must be resolved with preopens");103 @compileError("on WASI the global cache dir must be resolved with preopens");
86104
...@@ -91,56 +109,107 @@ pub fn resolveGlobalCacheDir(allocator: mem.Allocator) ![]u8 {...@@ -91,56 +109,107 @@ pub fn resolveGlobalCacheDir(allocator: mem.Allocator) ![]u8 {
91 if (builtin.os.tag != .windows) {109 if (builtin.os.tag != .windows) {
92 if (std.zig.EnvVar.XDG_CACHE_HOME.getPosix()) |cache_root| {110 if (std.zig.EnvVar.XDG_CACHE_HOME.getPosix()) |cache_root| {
93 if (cache_root.len > 0) {111 if (cache_root.len > 0) {
94 return fs.path.join(allocator, &[_][]const u8{ cache_root, appname });112 return fs.path.join(allocator, &.{ cache_root, appname });
95 }113 }
96 }114 }
97 if (std.zig.EnvVar.HOME.getPosix()) |home| {115 if (std.zig.EnvVar.HOME.getPosix()) |home| {
98 return fs.path.join(allocator, &[_][]const u8{ home, ".cache", appname });116 return fs.path.join(allocator, &.{ home, ".cache", appname });
99 }117 }
100 }118 }
101119
102 return fs.getAppDataDir(allocator, appname);120 return fs.getAppDataDir(allocator, appname);
103}121}
104122
105/// Similar to std.fs.path.resolve, with a few important differences:123/// Similar to `fs.path.resolve`, but converts to a cwd-relative path, or, if that would
106/// * If the input is an absolute path, check it against the cwd and try to124/// start with a relative up-dir (".."), an absolute path based on the cwd. Also, the cwd
107/// convert it to a relative path.125/// returns the empty string ("") instead of ".".
108/// * If the resulting path would start with a relative up-dir ("../"), instead
109/// return an absolute path based on the cwd.
110/// * When targeting WASI, fail with an error message if an absolute path is
111/// used.
112pub fn resolvePath(126pub fn resolvePath(
113 ally: mem.Allocator,127 gpa: Allocator,
114 p: []const u8,128 /// The return value of `getResolvedCwd`.
115) error{129 /// Passed as an argument to avoid pointlessly repeating the call.
116 OutOfMemory,130 cwd_resolved: []const u8,
117 CurrentWorkingDirectoryUnlinked,131 paths: []const []const u8,
118 Unexpected,132) Allocator.Error![]u8 {
119}![]u8 {133 if (builtin.target.os.tag == .wasi) {
120 if (fs.path.isAbsolute(p)) {134 std.debug.assert(mem.eql(u8, cwd_resolved, ""));
121 const cwd_path = try std.process.getCwdAlloc(ally);135 const res = try fs.path.resolve(gpa, paths);
122 defer ally.free(cwd_path);136 if (mem.eql(u8, res, ".")) {
123 const relative = try fs.path.relative(ally, cwd_path, p);137 gpa.free(res);
124 if (isUpDir(relative)) {138 return "";
125 ally.free(relative);
126 return ally.dupe(u8, p);
127 } else {
128 return relative;
129 }139 }
140 return res;
141 }
142
143 // Heuristic for a fast path: if no component is absolute and ".." never appears, we just need to resolve `paths`.
144 for (paths) |p| {
145 if (fs.path.isAbsolute(p)) break; // absolute path
146 if (mem.indexOf(u8, p, "..") != null) break; // may contain up-dir
130 } else {147 } else {
131 const resolved = try fs.path.resolve(ally, &.{p});148 // no absolute path, no "..".
132 if (isUpDir(resolved)) {149 const res = try fs.path.resolve(gpa, paths);
133 ally.free(resolved);150 if (mem.eql(u8, res, ".")) {
134 const cwd_path = try std.process.getCwdAlloc(ally);151 gpa.free(res);
135 defer ally.free(cwd_path);152 return "";
136 return fs.path.resolve(ally, &.{ cwd_path, p });
137 } else {
138 return resolved;
139 }153 }
154 std.debug.assert(!fs.path.isAbsolute(res));
155 std.debug.assert(!isUpDir(res));
156 return res;
157 }
158
159 // The fast path failed; resolve the whole thing.
160 // Optimization: `paths` often has just one element.
161 const path_resolved = switch (paths.len) {
162 0 => unreachable,
163 1 => try fs.path.resolve(gpa, &.{ cwd_resolved, paths[0] }),
164 else => r: {
165 const all_paths = try gpa.alloc([]const u8, paths.len + 1);
166 defer gpa.free(all_paths);
167 all_paths[0] = cwd_resolved;
168 @memcpy(all_paths[1..], paths);
169 break :r try fs.path.resolve(gpa, all_paths);
170 },
171 };
172 errdefer gpa.free(path_resolved);
173
174 std.debug.assert(fs.path.isAbsolute(path_resolved));
175 std.debug.assert(fs.path.isAbsolute(cwd_resolved));
176
177 if (!std.mem.startsWith(u8, path_resolved, cwd_resolved)) return path_resolved; // not in cwd
178 if (path_resolved.len == cwd_resolved.len) {
179 // equal to cwd
180 gpa.free(path_resolved);
181 return "";
140 }182 }
183 if (path_resolved[cwd_resolved.len] != std.fs.path.sep) return path_resolved; // not in cwd (last component differs)
184
185 // in cwd; extract sub path
186 const sub_path = try gpa.dupe(u8, path_resolved[cwd_resolved.len + 1 ..]);
187 gpa.free(path_resolved);
188 return sub_path;
141}189}
142190
143/// TODO move this to std.fs.path191/// TODO move this to std.fs.path
144pub fn isUpDir(p: []const u8) bool {192pub fn isUpDir(p: []const u8) bool {
145 return mem.startsWith(u8, p, "..") and (p.len == 2 or p[2] == fs.path.sep);193 return mem.startsWith(u8, p, "..") and (p.len == 2 or p[2] == fs.path.sep);
146}194}
195
196pub const default_local_zig_cache_basename = ".zig-cache";
197
198/// Searches upwards from `cwd` for a directory containing a `build.zig` file.
199/// If such a directory is found, returns the path to it joined to the `.zig_cache` name.
200/// Otherwise, returns `null`, indicating no suitable local cache location.
201pub fn resolveSuitableLocalCacheDir(arena: Allocator, cwd: []const u8) Allocator.Error!?[]u8 {
202 var cur_dir = cwd;
203 while (true) {
204 const joined = try fs.path.join(arena, &.{ cur_dir, Package.build_zig_basename });
205 if (fs.cwd().access(joined, .{})) |_| {
206 return try fs.path.join(arena, &.{ cur_dir, default_local_zig_cache_basename });
207 } else |err| switch (err) {
208 error.FileNotFound => {
209 cur_dir = fs.path.dirname(cur_dir) orelse return null;
210 continue;
211 },
212 else => return null,
213 }
214 }
215}
src/libs/freebsd.zig+16-22
...@@ -34,7 +34,7 @@ pub fn needsCrt0(output_mode: std.builtin.OutputMode) ?CrtFile {...@@ -34,7 +34,7 @@ pub fn needsCrt0(output_mode: std.builtin.OutputMode) ?CrtFile {
3434
35fn includePath(comp: *Compilation, arena: Allocator, sub_path: []const u8) ![]const u8 {35fn includePath(comp: *Compilation, arena: Allocator, sub_path: []const u8) ![]const u8 {
36 return path.join(arena, &.{36 return path.join(arena, &.{
37 comp.zig_lib_directory.path.?,37 comp.dirs.zig_lib.path.?,
38 "libc" ++ path.sep_str ++ "include",38 "libc" ++ path.sep_str ++ "include",
39 sub_path,39 sub_path,
40 });40 });
...@@ -42,7 +42,7 @@ fn includePath(comp: *Compilation, arena: Allocator, sub_path: []const u8) ![]co...@@ -42,7 +42,7 @@ fn includePath(comp: *Compilation, arena: Allocator, sub_path: []const u8) ![]co
4242
43fn csuPath(comp: *Compilation, arena: Allocator, sub_path: []const u8) ![]const u8 {43fn csuPath(comp: *Compilation, arena: Allocator, sub_path: []const u8) ![]const u8 {
44 return path.join(arena, &.{44 return path.join(arena, &.{
45 comp.zig_lib_directory.path.?,45 comp.dirs.zig_lib.path.?,
46 "libc" ++ path.sep_str ++ "freebsd" ++ path.sep_str ++ "lib" ++ path.sep_str ++ "csu",46 "libc" ++ path.sep_str ++ "freebsd" ++ path.sep_str ++ "lib" ++ path.sep_str ++ "csu",
47 sub_path,47 sub_path,
48 });48 });
...@@ -50,7 +50,7 @@ fn csuPath(comp: *Compilation, arena: Allocator, sub_path: []const u8) ![]const...@@ -50,7 +50,7 @@ fn csuPath(comp: *Compilation, arena: Allocator, sub_path: []const u8) ![]const
5050
51fn libcPath(comp: *Compilation, arena: Allocator, sub_path: []const u8) ![]const u8 {51fn libcPath(comp: *Compilation, arena: Allocator, sub_path: []const u8) ![]const u8 {
52 return path.join(arena, &.{52 return path.join(arena, &.{
53 comp.zig_lib_directory.path.?,53 comp.dirs.zig_lib.path.?,
54 "libc" ++ path.sep_str ++ "freebsd" ++ path.sep_str ++ "lib" ++ path.sep_str ++ "libc",54 "libc" ++ path.sep_str ++ "freebsd" ++ path.sep_str ++ "lib" ++ path.sep_str ++ "libc",
55 sub_path,55 sub_path,
56 });56 });
...@@ -438,11 +438,11 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye...@@ -438,11 +438,11 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye
438 // Use the global cache directory.438 // Use the global cache directory.
439 var cache: Cache = .{439 var cache: Cache = .{
440 .gpa = gpa,440 .gpa = gpa,
441 .manifest_dir = try comp.global_cache_directory.handle.makeOpenPath("h", .{}),441 .manifest_dir = try comp.dirs.global_cache.handle.makeOpenPath("h", .{}),
442 };442 };
443 cache.addPrefix(.{ .path = null, .handle = fs.cwd() });443 cache.addPrefix(.{ .path = null, .handle = fs.cwd() });
444 cache.addPrefix(comp.zig_lib_directory);444 cache.addPrefix(comp.dirs.zig_lib);
445 cache.addPrefix(comp.global_cache_directory);445 cache.addPrefix(comp.dirs.global_cache);
446 defer cache.manifest_dir.close();446 defer cache.manifest_dir.close();
447447
448 var man = cache.obtain();448 var man = cache.obtain();
...@@ -452,7 +452,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye...@@ -452,7 +452,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye
452 man.hash.add(target.abi);452 man.hash.add(target.abi);
453 man.hash.add(target_version);453 man.hash.add(target_version);
454454
455 const full_abilists_path = try comp.zig_lib_directory.join(arena, &.{abilists_path});455 const full_abilists_path = try comp.dirs.zig_lib.join(arena, &.{abilists_path});
456 const abilists_index = try man.addFile(full_abilists_path, abilists_max_size);456 const abilists_index = try man.addFile(full_abilists_path, abilists_max_size);
457457
458 if (try man.hit()) {458 if (try man.hit()) {
...@@ -461,7 +461,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye...@@ -461,7 +461,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye
461 return queueSharedObjects(comp, .{461 return queueSharedObjects(comp, .{
462 .lock = man.toOwnedLock(),462 .lock = man.toOwnedLock(),
463 .dir_path = .{463 .dir_path = .{
464 .root_dir = comp.global_cache_directory,464 .root_dir = comp.dirs.global_cache,
465 .sub_path = try gpa.dupe(u8, "o" ++ fs.path.sep_str ++ digest),465 .sub_path = try gpa.dupe(u8, "o" ++ fs.path.sep_str ++ digest),
466 },466 },
467 });467 });
...@@ -470,9 +470,9 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye...@@ -470,9 +470,9 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye
470 const digest = man.final();470 const digest = man.final();
471 const o_sub_path = try path.join(arena, &[_][]const u8{ "o", &digest });471 const o_sub_path = try path.join(arena, &[_][]const u8{ "o", &digest });
472472
473 var o_directory: Compilation.Directory = .{473 var o_directory: Cache.Directory = .{
474 .handle = try comp.global_cache_directory.handle.makeOpenPath(o_sub_path, .{}),474 .handle = try comp.dirs.global_cache.handle.makeOpenPath(o_sub_path, .{}),
475 .path = try comp.global_cache_directory.join(arena, &.{o_sub_path}),475 .path = try comp.dirs.global_cache.join(arena, &.{o_sub_path}),
476 };476 };
477 defer o_directory.handle.close();477 defer o_directory.handle.close();
478478
...@@ -974,7 +974,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye...@@ -974,7 +974,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye
974 var lib_name_buf: [32]u8 = undefined; // Larger than each of the names "c", "stdthreads", etc.974 var lib_name_buf: [32]u8 = undefined; // Larger than each of the names "c", "stdthreads", etc.
975 const asm_file_basename = std.fmt.bufPrint(&lib_name_buf, "{s}.s", .{lib.name}) catch unreachable;975 const asm_file_basename = std.fmt.bufPrint(&lib_name_buf, "{s}.s", .{lib.name}) catch unreachable;
976 try o_directory.handle.writeFile(.{ .sub_path = asm_file_basename, .data = stubs_asm.items });976 try o_directory.handle.writeFile(.{ .sub_path = asm_file_basename, .data = stubs_asm.items });
977 try buildSharedLib(comp, arena, comp.global_cache_directory, o_directory, asm_file_basename, lib, prog_node);977 try buildSharedLib(comp, arena, o_directory, asm_file_basename, lib, prog_node);
978 }978 }
979979
980 man.writeManifest() catch |err| {980 man.writeManifest() catch |err| {
...@@ -984,7 +984,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye...@@ -984,7 +984,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye
984 return queueSharedObjects(comp, .{984 return queueSharedObjects(comp, .{
985 .lock = man.toOwnedLock(),985 .lock = man.toOwnedLock(),
986 .dir_path = .{986 .dir_path = .{
987 .root_dir = comp.global_cache_directory,987 .root_dir = comp.dirs.global_cache,
988 .sub_path = try gpa.dupe(u8, "o" ++ fs.path.sep_str ++ digest),988 .sub_path = try gpa.dupe(u8, "o" ++ fs.path.sep_str ++ digest),
989 },989 },
990 });990 });
...@@ -1023,8 +1023,7 @@ fn queueSharedObjects(comp: *Compilation, so_files: BuiltSharedObjects) void {...@@ -1023,8 +1023,7 @@ fn queueSharedObjects(comp: *Compilation, so_files: BuiltSharedObjects) void {
1023fn buildSharedLib(1023fn buildSharedLib(
1024 comp: *Compilation,1024 comp: *Compilation,
1025 arena: Allocator,1025 arena: Allocator,
1026 zig_cache_directory: Compilation.Directory,1026 bin_directory: Cache.Directory,
1027 bin_directory: Compilation.Directory,
1028 asm_file_basename: []const u8,1027 asm_file_basename: []const u8,
1029 lib: Lib,1028 lib: Lib,
1030 prog_node: std.Progress.Node,1029 prog_node: std.Progress.Node,
...@@ -1057,9 +1056,8 @@ fn buildSharedLib(...@@ -1057,9 +1056,8 @@ fn buildSharedLib(
1057 });1056 });
10581057
1059 const root_mod = try Module.create(arena, .{1058 const root_mod = try Module.create(arena, .{
1060 .global_cache_directory = comp.global_cache_directory,
1061 .paths = .{1059 .paths = .{
1062 .root = .{ .root_dir = comp.zig_lib_directory },1060 .root = .zig_lib_root,
1063 .root_src_path = "",1061 .root_src_path = "",
1064 },1062 },
1065 .fully_qualified_name = "root",1063 .fully_qualified_name = "root",
...@@ -1079,8 +1077,6 @@ fn buildSharedLib(...@@ -1079,8 +1077,6 @@ fn buildSharedLib(
1079 .global = config,1077 .global = config,
1080 .cc_argv = &.{},1078 .cc_argv = &.{},
1081 .parent = null,1079 .parent = null,
1082 .builtin_mod = null,
1083 .builtin_modules = null, // there is only one module in this compilation
1084 });1080 });
10851081
1086 const c_source_files = [1]Compilation.CSourceFile{1082 const c_source_files = [1]Compilation.CSourceFile{
...@@ -1091,9 +1087,7 @@ fn buildSharedLib(...@@ -1091,9 +1087,7 @@ fn buildSharedLib(
1091 };1087 };
10921088
1093 const sub_compilation = try Compilation.create(comp.gpa, arena, .{1089 const sub_compilation = try Compilation.create(comp.gpa, arena, .{
1094 .local_cache_directory = zig_cache_directory,1090 .dirs = comp.dirs.withoutLocalCache(),
1095 .global_cache_directory = comp.global_cache_directory,
1096 .zig_lib_directory = comp.zig_lib_directory,
1097 .thread_pool = comp.thread_pool,1091 .thread_pool = comp.thread_pool,
1098 .self_exe_path = comp.self_exe_path,1092 .self_exe_path = comp.self_exe_path,
1099 .cache_mode = .incremental,1093 .cache_mode = .incremental,
src/libs/glibc.zig+19-29
...@@ -365,7 +365,7 @@ fn start_asm_path(comp: *Compilation, arena: Allocator, basename: []const u8) ![...@@ -365,7 +365,7 @@ fn start_asm_path(comp: *Compilation, arena: Allocator, basename: []const u8) ![
365 const s = path.sep_str;365 const s = path.sep_str;
366366
367 var result = std.ArrayList(u8).init(arena);367 var result = std.ArrayList(u8).init(arena);
368 try result.appendSlice(comp.zig_lib_directory.path.?);368 try result.appendSlice(comp.dirs.zig_lib.path orelse ".");
369 try result.appendSlice(s ++ "libc" ++ s ++ "glibc" ++ s ++ "sysdeps" ++ s);369 try result.appendSlice(s ++ "libc" ++ s ++ "glibc" ++ s ++ "sysdeps" ++ s);
370 if (is_sparc) {370 if (is_sparc) {
371 if (is_64) {371 if (is_64) {
...@@ -439,7 +439,7 @@ fn add_include_dirs(comp: *Compilation, arena: Allocator, args: *std.ArrayList([...@@ -439,7 +439,7 @@ fn add_include_dirs(comp: *Compilation, arena: Allocator, args: *std.ArrayList([
439 }439 }
440 if (opt_nptl) |nptl| {440 if (opt_nptl) |nptl| {
441 try args.append("-I");441 try args.append("-I");
442 try args.append(try path.join(arena, &[_][]const u8{ comp.zig_lib_directory.path.?, lib_libc_glibc ++ "sysdeps", nptl }));442 try args.append(try path.join(arena, &.{ comp.dirs.zig_lib.path orelse ".", lib_libc_glibc ++ "sysdeps", nptl }));
443 }443 }
444444
445 try args.append("-I");445 try args.append("-I");
...@@ -459,11 +459,11 @@ fn add_include_dirs(comp: *Compilation, arena: Allocator, args: *std.ArrayList([...@@ -459,11 +459,11 @@ fn add_include_dirs(comp: *Compilation, arena: Allocator, args: *std.ArrayList([
459 try args.append(try lib_path(comp, arena, lib_libc_glibc ++ "sysdeps" ++ s ++ "generic"));459 try args.append(try lib_path(comp, arena, lib_libc_glibc ++ "sysdeps" ++ s ++ "generic"));
460460
461 try args.append("-I");461 try args.append("-I");
462 try args.append(try path.join(arena, &[_][]const u8{ comp.zig_lib_directory.path.?, lib_libc ++ "glibc" }));462 try args.append(try path.join(arena, &[_][]const u8{ comp.dirs.zig_lib.path orelse ".", lib_libc ++ "glibc" }));
463463
464 try args.append("-I");464 try args.append("-I");
465 try args.append(try std.fmt.allocPrint(arena, "{s}" ++ s ++ "libc" ++ s ++ "include" ++ s ++ "{s}-{s}-{s}", .{465 try args.append(try std.fmt.allocPrint(arena, "{s}" ++ s ++ "libc" ++ s ++ "include" ++ s ++ "{s}-{s}-{s}", .{
466 comp.zig_lib_directory.path.?, @tagName(target.cpu.arch), @tagName(target.os.tag), @tagName(target.abi),466 comp.dirs.zig_lib.path orelse ".", @tagName(target.cpu.arch), @tagName(target.os.tag), @tagName(target.abi),
467 }));467 }));
468468
469 try args.append("-I");469 try args.append("-I");
...@@ -472,7 +472,7 @@ fn add_include_dirs(comp: *Compilation, arena: Allocator, args: *std.ArrayList([...@@ -472,7 +472,7 @@ fn add_include_dirs(comp: *Compilation, arena: Allocator, args: *std.ArrayList([
472 const arch_name = std.zig.target.osArchName(target);472 const arch_name = std.zig.target.osArchName(target);
473 try args.append("-I");473 try args.append("-I");
474 try args.append(try std.fmt.allocPrint(arena, "{s}" ++ s ++ "libc" ++ s ++ "include" ++ s ++ "{s}-linux-any", .{474 try args.append(try std.fmt.allocPrint(arena, "{s}" ++ s ++ "libc" ++ s ++ "include" ++ s ++ "{s}-linux-any", .{
475 comp.zig_lib_directory.path.?, arch_name,475 comp.dirs.zig_lib.path orelse ".", arch_name,
476 }));476 }));
477477
478 try args.append("-I");478 try args.append("-I");
...@@ -626,15 +626,11 @@ fn add_include_dirs_arch(...@@ -626,15 +626,11 @@ fn add_include_dirs_arch(
626 }626 }
627}627}
628628
629fn path_from_lib(comp: *Compilation, arena: Allocator, sub_path: []const u8) ![]const u8 {
630 return path.join(arena, &[_][]const u8{ comp.zig_lib_directory.path.?, sub_path });
631}
632
633const lib_libc = "libc" ++ path.sep_str;629const lib_libc = "libc" ++ path.sep_str;
634const lib_libc_glibc = lib_libc ++ "glibc" ++ path.sep_str;630const lib_libc_glibc = lib_libc ++ "glibc" ++ path.sep_str;
635631
636fn lib_path(comp: *Compilation, arena: Allocator, sub_path: []const u8) ![]const u8 {632fn lib_path(comp: *Compilation, arena: Allocator, sub_path: []const u8) ![]const u8 {
637 return path.join(arena, &[_][]const u8{ comp.zig_lib_directory.path.?, sub_path });633 return path.join(arena, &.{ comp.dirs.zig_lib.path orelse ".", sub_path });
638}634}
639635
640pub const BuiltSharedObjects = struct {636pub const BuiltSharedObjects = struct {
...@@ -678,11 +674,11 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye...@@ -678,11 +674,11 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye
678 // Use the global cache directory.674 // Use the global cache directory.
679 var cache: Cache = .{675 var cache: Cache = .{
680 .gpa = gpa,676 .gpa = gpa,
681 .manifest_dir = try comp.global_cache_directory.handle.makeOpenPath("h", .{}),677 .manifest_dir = try comp.dirs.global_cache.handle.makeOpenPath("h", .{}),
682 };678 };
683 cache.addPrefix(.{ .path = null, .handle = fs.cwd() });679 cache.addPrefix(.{ .path = null, .handle = fs.cwd() });
684 cache.addPrefix(comp.zig_lib_directory);680 cache.addPrefix(comp.dirs.zig_lib);
685 cache.addPrefix(comp.global_cache_directory);681 cache.addPrefix(comp.dirs.global_cache);
686 defer cache.manifest_dir.close();682 defer cache.manifest_dir.close();
687683
688 var man = cache.obtain();684 var man = cache.obtain();
...@@ -692,7 +688,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye...@@ -692,7 +688,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye
692 man.hash.add(target.abi);688 man.hash.add(target.abi);
693 man.hash.add(target_version);689 man.hash.add(target_version);
694690
695 const full_abilists_path = try comp.zig_lib_directory.join(arena, &.{abilists_path});691 const full_abilists_path = try comp.dirs.zig_lib.join(arena, &.{abilists_path});
696 const abilists_index = try man.addFile(full_abilists_path, abilists_max_size);692 const abilists_index = try man.addFile(full_abilists_path, abilists_max_size);
697693
698 if (try man.hit()) {694 if (try man.hit()) {
...@@ -701,7 +697,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye...@@ -701,7 +697,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye
701 return queueSharedObjects(comp, .{697 return queueSharedObjects(comp, .{
702 .lock = man.toOwnedLock(),698 .lock = man.toOwnedLock(),
703 .dir_path = .{699 .dir_path = .{
704 .root_dir = comp.global_cache_directory,700 .root_dir = comp.dirs.global_cache,
705 .sub_path = try gpa.dupe(u8, "o" ++ fs.path.sep_str ++ digest),701 .sub_path = try gpa.dupe(u8, "o" ++ fs.path.sep_str ++ digest),
706 },702 },
707 });703 });
...@@ -710,9 +706,9 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye...@@ -710,9 +706,9 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye
710 const digest = man.final();706 const digest = man.final();
711 const o_sub_path = try path.join(arena, &[_][]const u8{ "o", &digest });707 const o_sub_path = try path.join(arena, &[_][]const u8{ "o", &digest });
712708
713 var o_directory: Compilation.Directory = .{709 var o_directory: Cache.Directory = .{
714 .handle = try comp.global_cache_directory.handle.makeOpenPath(o_sub_path, .{}),710 .handle = try comp.dirs.global_cache.handle.makeOpenPath(o_sub_path, .{}),
715 .path = try comp.global_cache_directory.join(arena, &.{o_sub_path}),711 .path = try comp.dirs.global_cache.join(arena, &.{o_sub_path}),
716 };712 };
717 defer o_directory.handle.close();713 defer o_directory.handle.close();
718714
...@@ -1112,7 +1108,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye...@@ -1112,7 +1108,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye
1112 var lib_name_buf: [32]u8 = undefined; // Larger than each of the names "c", "pthread", etc.1108 var lib_name_buf: [32]u8 = undefined; // Larger than each of the names "c", "pthread", etc.
1113 const asm_file_basename = std.fmt.bufPrint(&lib_name_buf, "{s}.s", .{lib.name}) catch unreachable;1109 const asm_file_basename = std.fmt.bufPrint(&lib_name_buf, "{s}.s", .{lib.name}) catch unreachable;
1114 try o_directory.handle.writeFile(.{ .sub_path = asm_file_basename, .data = stubs_asm.items });1110 try o_directory.handle.writeFile(.{ .sub_path = asm_file_basename, .data = stubs_asm.items });
1115 try buildSharedLib(comp, arena, comp.global_cache_directory, o_directory, asm_file_basename, lib, prog_node);1111 try buildSharedLib(comp, arena, o_directory, asm_file_basename, lib, prog_node);
1116 }1112 }
11171113
1118 man.writeManifest() catch |err| {1114 man.writeManifest() catch |err| {
...@@ -1122,7 +1118,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye...@@ -1122,7 +1118,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye
1122 return queueSharedObjects(comp, .{1118 return queueSharedObjects(comp, .{
1123 .lock = man.toOwnedLock(),1119 .lock = man.toOwnedLock(),
1124 .dir_path = .{1120 .dir_path = .{
1125 .root_dir = comp.global_cache_directory,1121 .root_dir = comp.dirs.global_cache,
1126 .sub_path = try gpa.dupe(u8, "o" ++ fs.path.sep_str ++ digest),1122 .sub_path = try gpa.dupe(u8, "o" ++ fs.path.sep_str ++ digest),
1127 },1123 },
1128 });1124 });
...@@ -1174,8 +1170,7 @@ fn queueSharedObjects(comp: *Compilation, so_files: BuiltSharedObjects) void {...@@ -1174,8 +1170,7 @@ fn queueSharedObjects(comp: *Compilation, so_files: BuiltSharedObjects) void {
1174fn buildSharedLib(1170fn buildSharedLib(
1175 comp: *Compilation,1171 comp: *Compilation,
1176 arena: Allocator,1172 arena: Allocator,
1177 zig_cache_directory: Compilation.Directory,1173 bin_directory: Cache.Directory,
1178 bin_directory: Compilation.Directory,
1179 asm_file_basename: []const u8,1174 asm_file_basename: []const u8,
1180 lib: Lib,1175 lib: Lib,
1181 prog_node: std.Progress.Node,1176 prog_node: std.Progress.Node,
...@@ -1208,9 +1203,8 @@ fn buildSharedLib(...@@ -1208,9 +1203,8 @@ fn buildSharedLib(
1208 });1203 });
12091204
1210 const root_mod = try Module.create(arena, .{1205 const root_mod = try Module.create(arena, .{
1211 .global_cache_directory = comp.global_cache_directory,
1212 .paths = .{1206 .paths = .{
1213 .root = .{ .root_dir = comp.zig_lib_directory },1207 .root = .zig_lib_root,
1214 .root_src_path = "",1208 .root_src_path = "",
1215 },1209 },
1216 .fully_qualified_name = "root",1210 .fully_qualified_name = "root",
...@@ -1230,8 +1224,6 @@ fn buildSharedLib(...@@ -1230,8 +1224,6 @@ fn buildSharedLib(
1230 .global = config,1224 .global = config,
1231 .cc_argv = &.{},1225 .cc_argv = &.{},
1232 .parent = null,1226 .parent = null,
1233 .builtin_mod = null,
1234 .builtin_modules = null, // there is only one module in this compilation
1235 });1227 });
12361228
1237 const c_source_files = [1]Compilation.CSourceFile{1229 const c_source_files = [1]Compilation.CSourceFile{
...@@ -1242,9 +1234,7 @@ fn buildSharedLib(...@@ -1242,9 +1234,7 @@ fn buildSharedLib(
1242 };1234 };
12431235
1244 const sub_compilation = try Compilation.create(comp.gpa, arena, .{1236 const sub_compilation = try Compilation.create(comp.gpa, arena, .{
1245 .local_cache_directory = zig_cache_directory,1237 .dirs = comp.dirs.withoutLocalCache(),
1246 .global_cache_directory = comp.global_cache_directory,
1247 .zig_lib_directory = comp.zig_lib_directory,
1248 .thread_pool = comp.thread_pool,1238 .thread_pool = comp.thread_pool,
1249 .self_exe_path = comp.self_exe_path,1239 .self_exe_path = comp.self_exe_path,
1250 .cache_mode = .incremental,1240 .cache_mode = .incremental,
src/libs/libcxx.zig+13-23
...@@ -134,10 +134,10 @@ pub fn buildLibCxx(comp: *Compilation, prog_node: std.Progress.Node) BuildError!...@@ -134,10 +134,10 @@ pub fn buildLibCxx(comp: *Compilation, prog_node: std.Progress.Node) BuildError!
134 .basename = basename,134 .basename = basename,
135 };135 };
136136
137 const cxxabi_include_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libcxxabi", "include" });137 const cxxabi_include_path = try comp.dirs.zig_lib.join(arena, &.{ "libcxxabi", "include" });
138 const cxx_include_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libcxx", "include" });138 const cxx_include_path = try comp.dirs.zig_lib.join(arena, &.{ "libcxx", "include" });
139 const cxx_src_include_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libcxx", "src" });139 const cxx_src_include_path = try comp.dirs.zig_lib.join(arena, &.{ "libcxx", "src" });
140 const cxx_libc_include_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libcxx", "libc" });140 const cxx_libc_include_path = try comp.dirs.zig_lib.join(arena, &.{ "libcxx", "libc" });
141141
142 const optimize_mode = comp.compilerRtOptMode();142 const optimize_mode = comp.compilerRtOptMode();
143 const strip = comp.compilerRtStrip();143 const strip = comp.compilerRtStrip();
...@@ -164,9 +164,8 @@ pub fn buildLibCxx(comp: *Compilation, prog_node: std.Progress.Node) BuildError!...@@ -164,9 +164,8 @@ pub fn buildLibCxx(comp: *Compilation, prog_node: std.Progress.Node) BuildError!
164 };164 };
165165
166 const root_mod = Module.create(arena, .{166 const root_mod = Module.create(arena, .{
167 .global_cache_directory = comp.global_cache_directory,
168 .paths = .{167 .paths = .{
169 .root = .{ .root_dir = comp.zig_lib_directory },168 .root = .zig_lib_root,
170 .root_src_path = "",169 .root_src_path = "",
171 },170 },
172 .fully_qualified_name = "root",171 .fully_qualified_name = "root",
...@@ -188,8 +187,6 @@ pub fn buildLibCxx(comp: *Compilation, prog_node: std.Progress.Node) BuildError!...@@ -188,8 +187,6 @@ pub fn buildLibCxx(comp: *Compilation, prog_node: std.Progress.Node) BuildError!
188 .global = config,187 .global = config,
189 .cc_argv = &.{},188 .cc_argv = &.{},
190 .parent = null,189 .parent = null,
191 .builtin_mod = null,
192 .builtin_modules = null, // there is only one module in this compilation
193 }) catch |err| {190 }) catch |err| {
194 comp.setMiscFailure(191 comp.setMiscFailure(
195 .libcxx,192 .libcxx,
...@@ -258,7 +255,7 @@ pub fn buildLibCxx(comp: *Compilation, prog_node: std.Progress.Node) BuildError!...@@ -258,7 +255,7 @@ pub fn buildLibCxx(comp: *Compilation, prog_node: std.Progress.Node) BuildError!
258 try cache_exempt_flags.append(cxx_libc_include_path);255 try cache_exempt_flags.append(cxx_libc_include_path);
259256
260 c_source_files.appendAssumeCapacity(.{257 c_source_files.appendAssumeCapacity(.{
261 .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libcxx", cxx_src }),258 .src_path = try comp.dirs.zig_lib.join(arena, &.{ "libcxx", cxx_src }),
262 .extra_flags = cflags.items,259 .extra_flags = cflags.items,
263 .cache_exempt_flags = cache_exempt_flags.items,260 .cache_exempt_flags = cache_exempt_flags.items,
264 .owner = root_mod,261 .owner = root_mod,
...@@ -266,9 +263,7 @@ pub fn buildLibCxx(comp: *Compilation, prog_node: std.Progress.Node) BuildError!...@@ -266,9 +263,7 @@ pub fn buildLibCxx(comp: *Compilation, prog_node: std.Progress.Node) BuildError!
266 }263 }
267264
268 const sub_compilation = Compilation.create(comp.gpa, arena, .{265 const sub_compilation = Compilation.create(comp.gpa, arena, .{
269 .local_cache_directory = comp.global_cache_directory,266 .dirs = comp.dirs.withoutLocalCache(),
270 .global_cache_directory = comp.global_cache_directory,
271 .zig_lib_directory = comp.zig_lib_directory,
272 .self_exe_path = comp.self_exe_path,267 .self_exe_path = comp.self_exe_path,
273 .cache_mode = .whole,268 .cache_mode = .whole,
274 .config = config,269 .config = config,
...@@ -344,9 +339,9 @@ pub fn buildLibCxxAbi(comp: *Compilation, prog_node: std.Progress.Node) BuildErr...@@ -344,9 +339,9 @@ pub fn buildLibCxxAbi(comp: *Compilation, prog_node: std.Progress.Node) BuildErr
344 .basename = basename,339 .basename = basename,
345 };340 };
346341
347 const cxxabi_include_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libcxxabi", "include" });342 const cxxabi_include_path = try comp.dirs.zig_lib.join(arena, &.{ "libcxxabi", "include" });
348 const cxx_include_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libcxx", "include" });343 const cxx_include_path = try comp.dirs.zig_lib.join(arena, &.{ "libcxx", "include" });
349 const cxx_src_include_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libcxx", "src" });344 const cxx_src_include_path = try comp.dirs.zig_lib.join(arena, &.{ "libcxx", "src" });
350345
351 const optimize_mode = comp.compilerRtOptMode();346 const optimize_mode = comp.compilerRtOptMode();
352 const strip = comp.compilerRtStrip();347 const strip = comp.compilerRtStrip();
...@@ -378,9 +373,8 @@ pub fn buildLibCxxAbi(comp: *Compilation, prog_node: std.Progress.Node) BuildErr...@@ -378,9 +373,8 @@ pub fn buildLibCxxAbi(comp: *Compilation, prog_node: std.Progress.Node) BuildErr
378 };373 };
379374
380 const root_mod = Module.create(arena, .{375 const root_mod = Module.create(arena, .{
381 .global_cache_directory = comp.global_cache_directory,
382 .paths = .{376 .paths = .{
383 .root = .{ .root_dir = comp.zig_lib_directory },377 .root = .zig_lib_root,
384 .root_src_path = "",378 .root_src_path = "",
385 },379 },
386 .fully_qualified_name = "root",380 .fully_qualified_name = "root",
...@@ -403,8 +397,6 @@ pub fn buildLibCxxAbi(comp: *Compilation, prog_node: std.Progress.Node) BuildErr...@@ -403,8 +397,6 @@ pub fn buildLibCxxAbi(comp: *Compilation, prog_node: std.Progress.Node) BuildErr
403 .global = config,397 .global = config,
404 .cc_argv = &.{},398 .cc_argv = &.{},
405 .parent = null,399 .parent = null,
406 .builtin_mod = null,
407 .builtin_modules = null, // there is only one module in this compilation
408 }) catch |err| {400 }) catch |err| {
409 comp.setMiscFailure(401 comp.setMiscFailure(
410 .libcxxabi,402 .libcxxabi,
...@@ -459,7 +451,7 @@ pub fn buildLibCxxAbi(comp: *Compilation, prog_node: std.Progress.Node) BuildErr...@@ -459,7 +451,7 @@ pub fn buildLibCxxAbi(comp: *Compilation, prog_node: std.Progress.Node) BuildErr
459 try cache_exempt_flags.append(cxx_src_include_path);451 try cache_exempt_flags.append(cxx_src_include_path);
460452
461 c_source_files.appendAssumeCapacity(.{453 c_source_files.appendAssumeCapacity(.{
462 .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libcxxabi", cxxabi_src }),454 .src_path = try comp.dirs.zig_lib.join(arena, &.{ "libcxxabi", cxxabi_src }),
463 .extra_flags = cflags.items,455 .extra_flags = cflags.items,
464 .cache_exempt_flags = cache_exempt_flags.items,456 .cache_exempt_flags = cache_exempt_flags.items,
465 .owner = root_mod,457 .owner = root_mod,
...@@ -467,9 +459,7 @@ pub fn buildLibCxxAbi(comp: *Compilation, prog_node: std.Progress.Node) BuildErr...@@ -467,9 +459,7 @@ pub fn buildLibCxxAbi(comp: *Compilation, prog_node: std.Progress.Node) BuildErr
467 }459 }
468460
469 const sub_compilation = Compilation.create(comp.gpa, arena, .{461 const sub_compilation = Compilation.create(comp.gpa, arena, .{
470 .local_cache_directory = comp.global_cache_directory,462 .dirs = comp.dirs.withoutLocalCache(),
471 .global_cache_directory = comp.global_cache_directory,
472 .zig_lib_directory = comp.zig_lib_directory,
473 .self_exe_path = comp.self_exe_path,463 .self_exe_path = comp.self_exe_path,
474 .cache_mode = .whole,464 .cache_mode = .whole,
475 .config = config,465 .config = config,
src/libs/libtsan.zig+12-20
...@@ -84,9 +84,8 @@ pub fn buildTsan(comp: *Compilation, prog_node: std.Progress.Node) BuildError!vo...@@ -84,9 +84,8 @@ pub fn buildTsan(comp: *Compilation, prog_node: std.Progress.Node) BuildError!vo
84 };84 };
8585
86 const root_mod = Module.create(arena, .{86 const root_mod = Module.create(arena, .{
87 .global_cache_directory = comp.global_cache_directory,
88 .paths = .{87 .paths = .{
89 .root = .{ .root_dir = comp.zig_lib_directory },88 .root = .zig_lib_root,
90 .root_src_path = "",89 .root_src_path = "",
91 },90 },
92 .fully_qualified_name = "root",91 .fully_qualified_name = "root",
...@@ -110,8 +109,6 @@ pub fn buildTsan(comp: *Compilation, prog_node: std.Progress.Node) BuildError!vo...@@ -110,8 +109,6 @@ pub fn buildTsan(comp: *Compilation, prog_node: std.Progress.Node) BuildError!vo
110 .global = config,109 .global = config,
111 .cc_argv = &common_flags,110 .cc_argv = &common_flags,
112 .parent = null,111 .parent = null,
113 .builtin_mod = null,
114 .builtin_modules = null, // there is only one module in this compilation
115 }) catch |err| {112 }) catch |err| {
116 comp.setMiscFailure(113 comp.setMiscFailure(
117 .libtsan,114 .libtsan,
...@@ -124,7 +121,7 @@ pub fn buildTsan(comp: *Compilation, prog_node: std.Progress.Node) BuildError!vo...@@ -124,7 +121,7 @@ pub fn buildTsan(comp: *Compilation, prog_node: std.Progress.Node) BuildError!vo
124 var c_source_files = std.ArrayList(Compilation.CSourceFile).init(arena);121 var c_source_files = std.ArrayList(Compilation.CSourceFile).init(arena);
125 try c_source_files.ensureUnusedCapacity(tsan_sources.len);122 try c_source_files.ensureUnusedCapacity(tsan_sources.len);
126123
127 const tsan_include_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{"libtsan"});124 const tsan_include_path = try comp.dirs.zig_lib.join(arena, &.{"libtsan"});
128 for (tsan_sources) |tsan_src| {125 for (tsan_sources) |tsan_src| {
129 var cflags = std.ArrayList([]const u8).init(arena);126 var cflags = std.ArrayList([]const u8).init(arena);
130127
...@@ -134,7 +131,7 @@ pub fn buildTsan(comp: *Compilation, prog_node: std.Progress.Node) BuildError!vo...@@ -134,7 +131,7 @@ pub fn buildTsan(comp: *Compilation, prog_node: std.Progress.Node) BuildError!vo
134 try addCcArgs(target, &cflags);131 try addCcArgs(target, &cflags);
135132
136 c_source_files.appendAssumeCapacity(.{133 c_source_files.appendAssumeCapacity(.{
137 .src_path = try comp.zig_lib_directory.join(arena, &.{ "libtsan", tsan_src }),134 .src_path = try comp.dirs.zig_lib.join(arena, &.{ "libtsan", tsan_src }),
138 .extra_flags = cflags.items,135 .extra_flags = cflags.items,
139 .owner = root_mod,136 .owner = root_mod,
140 });137 });
...@@ -155,7 +152,7 @@ pub fn buildTsan(comp: *Compilation, prog_node: std.Progress.Node) BuildError!vo...@@ -155,7 +152,7 @@ pub fn buildTsan(comp: *Compilation, prog_node: std.Progress.Node) BuildError!vo
155 try addCcArgs(target, &cflags);152 try addCcArgs(target, &cflags);
156153
157 c_source_files.appendAssumeCapacity(.{154 c_source_files.appendAssumeCapacity(.{
158 .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libtsan", tsan_src }),155 .src_path = try comp.dirs.zig_lib.join(arena, &.{ "libtsan", tsan_src }),
159 .extra_flags = cflags.items,156 .extra_flags = cflags.items,
160 .owner = root_mod,157 .owner = root_mod,
161 });158 });
...@@ -179,14 +176,14 @@ pub fn buildTsan(comp: *Compilation, prog_node: std.Progress.Node) BuildError!vo...@@ -179,14 +176,14 @@ pub fn buildTsan(comp: *Compilation, prog_node: std.Progress.Node) BuildError!vo
179 try cflags.append("-DNDEBUG");176 try cflags.append("-DNDEBUG");
180177
181 c_source_files.appendAssumeCapacity(.{178 c_source_files.appendAssumeCapacity(.{
182 .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libtsan", asm_source }),179 .src_path = try comp.dirs.zig_lib.join(arena, &.{ "libtsan", asm_source }),
183 .extra_flags = cflags.items,180 .extra_flags = cflags.items,
184 .owner = root_mod,181 .owner = root_mod,
185 });182 });
186 }183 }
187184
188 try c_source_files.ensureUnusedCapacity(sanitizer_common_sources.len);185 try c_source_files.ensureUnusedCapacity(sanitizer_common_sources.len);
189 const sanitizer_common_include_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{186 const sanitizer_common_include_path = try comp.dirs.zig_lib.join(arena, &.{
190 "libtsan", "sanitizer_common",187 "libtsan", "sanitizer_common",
191 });188 });
192 for (sanitizer_common_sources) |common_src| {189 for (sanitizer_common_sources) |common_src| {
...@@ -200,7 +197,7 @@ pub fn buildTsan(comp: *Compilation, prog_node: std.Progress.Node) BuildError!vo...@@ -200,7 +197,7 @@ pub fn buildTsan(comp: *Compilation, prog_node: std.Progress.Node) BuildError!vo
200 try addCcArgs(target, &cflags);197 try addCcArgs(target, &cflags);
201198
202 c_source_files.appendAssumeCapacity(.{199 c_source_files.appendAssumeCapacity(.{
203 .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{200 .src_path = try comp.dirs.zig_lib.join(arena, &.{
204 "libtsan", "sanitizer_common", common_src,201 "libtsan", "sanitizer_common", common_src,
205 }),202 }),
206 .extra_flags = cflags.items,203 .extra_flags = cflags.items,
...@@ -224,7 +221,7 @@ pub fn buildTsan(comp: *Compilation, prog_node: std.Progress.Node) BuildError!vo...@@ -224,7 +221,7 @@ pub fn buildTsan(comp: *Compilation, prog_node: std.Progress.Node) BuildError!vo
224 try addCcArgs(target, &cflags);221 try addCcArgs(target, &cflags);
225222
226 c_source_files.appendAssumeCapacity(.{223 c_source_files.appendAssumeCapacity(.{
227 .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{224 .src_path = try comp.dirs.zig_lib.join(arena, &.{
228 "libtsan", "sanitizer_common", c_src,225 "libtsan", "sanitizer_common", c_src,
229 }),226 }),
230 .extra_flags = cflags.items,227 .extra_flags = cflags.items,
...@@ -242,7 +239,7 @@ pub fn buildTsan(comp: *Compilation, prog_node: std.Progress.Node) BuildError!vo...@@ -242,7 +239,7 @@ pub fn buildTsan(comp: *Compilation, prog_node: std.Progress.Node) BuildError!vo
242 try addCcArgs(target, &cflags);239 try addCcArgs(target, &cflags);
243240
244 c_source_files.appendAssumeCapacity(.{241 c_source_files.appendAssumeCapacity(.{
245 .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{242 .src_path = try comp.dirs.zig_lib.join(arena, &.{
246 "libtsan", "sanitizer_common", c_src,243 "libtsan", "sanitizer_common", c_src,
247 }),244 }),
248 .extra_flags = cflags.items,245 .extra_flags = cflags.items,
...@@ -250,10 +247,7 @@ pub fn buildTsan(comp: *Compilation, prog_node: std.Progress.Node) BuildError!vo...@@ -250,10 +247,7 @@ pub fn buildTsan(comp: *Compilation, prog_node: std.Progress.Node) BuildError!vo
250 });247 });
251 }248 }
252249
253 const interception_include_path = try comp.zig_lib_directory.join(250 const interception_include_path = try comp.dirs.zig_lib.join(arena, &.{"interception"});
254 arena,
255 &[_][]const u8{"interception"},
256 );
257251
258 try c_source_files.ensureUnusedCapacity(interception_sources.len);252 try c_source_files.ensureUnusedCapacity(interception_sources.len);
259 for (interception_sources) |c_src| {253 for (interception_sources) |c_src| {
...@@ -268,7 +262,7 @@ pub fn buildTsan(comp: *Compilation, prog_node: std.Progress.Node) BuildError!vo...@@ -268,7 +262,7 @@ pub fn buildTsan(comp: *Compilation, prog_node: std.Progress.Node) BuildError!vo
268 try addCcArgs(target, &cflags);262 try addCcArgs(target, &cflags);
269263
270 c_source_files.appendAssumeCapacity(.{264 c_source_files.appendAssumeCapacity(.{
271 .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{265 .src_path = try comp.dirs.zig_lib.join(arena, &.{
272 "libtsan", "interception", c_src,266 "libtsan", "interception", c_src,
273 }),267 }),
274 .extra_flags = cflags.items,268 .extra_flags = cflags.items,
...@@ -285,9 +279,7 @@ pub fn buildTsan(comp: *Compilation, prog_node: std.Progress.Node) BuildError!vo...@@ -285,9 +279,7 @@ pub fn buildTsan(comp: *Compilation, prog_node: std.Progress.Node) BuildError!vo
285 // Workaround for https://github.com/llvm/llvm-project/issues/97627279 // Workaround for https://github.com/llvm/llvm-project/issues/97627
286 const headerpad_size: ?u32 = if (target.os.tag.isDarwin()) 32 else null;280 const headerpad_size: ?u32 = if (target.os.tag.isDarwin()) 32 else null;
287 const sub_compilation = Compilation.create(comp.gpa, arena, .{281 const sub_compilation = Compilation.create(comp.gpa, arena, .{
288 .local_cache_directory = comp.global_cache_directory,282 .dirs = comp.dirs.withoutLocalCache(),
289 .global_cache_directory = comp.global_cache_directory,
290 .zig_lib_directory = comp.zig_lib_directory,
291 .thread_pool = comp.thread_pool,283 .thread_pool = comp.thread_pool,
292 .self_exe_path = comp.self_exe_path,284 .self_exe_path = comp.self_exe_path,
293 .cache_mode = .whole,285 .cache_mode = .whole,
src/libs/libunwind.zig+4-9
...@@ -50,9 +50,8 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: std.Progress.Node) BuildErr...@@ -50,9 +50,8 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: std.Progress.Node) BuildErr
50 return error.SubCompilationFailed;50 return error.SubCompilationFailed;
51 };51 };
52 const root_mod = Module.create(arena, .{52 const root_mod = Module.create(arena, .{
53 .global_cache_directory = comp.global_cache_directory,
54 .paths = .{53 .paths = .{
55 .root = .{ .root_dir = comp.zig_lib_directory },54 .root = .zig_lib_root,
56 .root_src_path = "",55 .root_src_path = "",
57 },56 },
58 .fully_qualified_name = "root",57 .fully_qualified_name = "root",
...@@ -76,8 +75,6 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: std.Progress.Node) BuildErr...@@ -76,8 +75,6 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: std.Progress.Node) BuildErr
76 .global = config,75 .global = config,
77 .cc_argv = &.{},76 .cc_argv = &.{},
78 .parent = null,77 .parent = null,
79 .builtin_mod = null,
80 .builtin_modules = null, // there is only one module in this compilation
81 }) catch |err| {78 }) catch |err| {
82 comp.setMiscFailure(79 comp.setMiscFailure(
83 .libunwind,80 .libunwind,
...@@ -118,7 +115,7 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: std.Progress.Node) BuildErr...@@ -118,7 +115,7 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: std.Progress.Node) BuildErr
118 else => unreachable, // See `unwind_src_list`.115 else => unreachable, // See `unwind_src_list`.
119 }116 }
120 try cflags.append("-I");117 try cflags.append("-I");
121 try cflags.append(try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libunwind", "include" }));118 try cflags.append(try comp.dirs.zig_lib.join(arena, &.{ "libunwind", "include" }));
122 try cflags.append("-D_LIBUNWIND_HIDE_SYMBOLS");119 try cflags.append("-D_LIBUNWIND_HIDE_SYMBOLS");
123 try cflags.append("-Wa,--noexecstack");120 try cflags.append("-Wa,--noexecstack");
124 try cflags.append("-fvisibility=hidden");121 try cflags.append("-fvisibility=hidden");
...@@ -148,16 +145,14 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: std.Progress.Node) BuildErr...@@ -148,16 +145,14 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: std.Progress.Node) BuildErr
148 }145 }
149146
150 c_source_files[i] = .{147 c_source_files[i] = .{
151 .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{unwind_src}),148 .src_path = try comp.dirs.zig_lib.join(arena, &.{unwind_src}),
152 .extra_flags = cflags.items,149 .extra_flags = cflags.items,
153 .owner = root_mod,150 .owner = root_mod,
154 };151 };
155 }152 }
156 const sub_compilation = Compilation.create(comp.gpa, arena, .{153 const sub_compilation = Compilation.create(comp.gpa, arena, .{
154 .dirs = comp.dirs.withoutLocalCache(),
157 .self_exe_path = comp.self_exe_path,155 .self_exe_path = comp.self_exe_path,
158 .local_cache_directory = comp.global_cache_directory,
159 .global_cache_directory = comp.global_cache_directory,
160 .zig_lib_directory = comp.zig_lib_directory,
161 .config = config,156 .config = config,
162 .root_mod = root_mod,157 .root_mod = root_mod,
163 .cache_mode = .whole,158 .cache_mode = .whole,
src/libs/mingw.zig+23-23
...@@ -40,7 +40,7 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre...@@ -40,7 +40,7 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre
40 }40 }
41 var files = [_]Compilation.CSourceFile{41 var files = [_]Compilation.CSourceFile{
42 .{42 .{
43 .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{43 .src_path = try comp.dirs.zig_lib.join(arena, &.{
44 "libc", "mingw", "crt", "crtexe.c",44 "libc", "mingw", "crt", "crtexe.c",
45 }),45 }),
46 .extra_flags = args.items,46 .extra_flags = args.items,
...@@ -57,7 +57,7 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre...@@ -57,7 +57,7 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre
57 try addCrtCcArgs(comp, arena, &args);57 try addCrtCcArgs(comp, arena, &args);
58 var files = [_]Compilation.CSourceFile{58 var files = [_]Compilation.CSourceFile{
59 .{59 .{
60 .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{60 .src_path = try comp.dirs.zig_lib.join(arena, &.{
61 "libc", "mingw", "crt", "crtdll.c",61 "libc", "mingw", "crt", "crtdll.c",
62 }),62 }),
63 .extra_flags = args.items,63 .extra_flags = args.items,
...@@ -78,7 +78,7 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre...@@ -78,7 +78,7 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre
7878
79 for (mingw32_generic_src) |dep| {79 for (mingw32_generic_src) |dep| {
80 try c_source_files.append(.{80 try c_source_files.append(.{
81 .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{81 .src_path = try comp.dirs.zig_lib.join(arena, &.{
82 "libc", "mingw", dep,82 "libc", "mingw", dep,
83 }),83 }),
84 .extra_flags = crt_args.items,84 .extra_flags = crt_args.items,
...@@ -88,7 +88,7 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre...@@ -88,7 +88,7 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre
88 if (target.cpu.arch.isX86()) {88 if (target.cpu.arch.isX86()) {
89 for (mingw32_x86_src) |dep| {89 for (mingw32_x86_src) |dep| {
90 try c_source_files.append(.{90 try c_source_files.append(.{
91 .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{91 .src_path = try comp.dirs.zig_lib.join(arena, &.{
92 "libc", "mingw", dep,92 "libc", "mingw", dep,
93 }),93 }),
94 .extra_flags = crt_args.items,94 .extra_flags = crt_args.items,
...@@ -98,7 +98,7 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre...@@ -98,7 +98,7 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre
98 if (target.cpu.arch == .x86) {98 if (target.cpu.arch == .x86) {
99 for (mingw32_x86_32_src) |dep| {99 for (mingw32_x86_32_src) |dep| {
100 try c_source_files.append(.{100 try c_source_files.append(.{
101 .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{101 .src_path = try comp.dirs.zig_lib.join(arena, &.{
102 "libc", "mingw", dep,102 "libc", "mingw", dep,
103 }),103 }),
104 .extra_flags = crt_args.items,104 .extra_flags = crt_args.items,
...@@ -109,7 +109,7 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre...@@ -109,7 +109,7 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre
109 } else if (target.cpu.arch == .thumb) {109 } else if (target.cpu.arch == .thumb) {
110 for (mingw32_arm_src) |dep| {110 for (mingw32_arm_src) |dep| {
111 try c_source_files.append(.{111 try c_source_files.append(.{
112 .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{112 .src_path = try comp.dirs.zig_lib.join(arena, &.{
113 "libc", "mingw", dep,113 "libc", "mingw", dep,
114 }),114 }),
115 .extra_flags = crt_args.items,115 .extra_flags = crt_args.items,
...@@ -118,7 +118,7 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre...@@ -118,7 +118,7 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre
118 }118 }
119 for (mingw32_arm32_src) |dep| {119 for (mingw32_arm32_src) |dep| {
120 try c_source_files.append(.{120 try c_source_files.append(.{
121 .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{121 .src_path = try comp.dirs.zig_lib.join(arena, &.{
122 "libc", "mingw", dep,122 "libc", "mingw", dep,
123 }),123 }),
124 .extra_flags = crt_args.items,124 .extra_flags = crt_args.items,
...@@ -128,7 +128,7 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre...@@ -128,7 +128,7 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre
128 } else if (target.cpu.arch == .aarch64) {128 } else if (target.cpu.arch == .aarch64) {
129 for (mingw32_arm_src) |dep| {129 for (mingw32_arm_src) |dep| {
130 try c_source_files.append(.{130 try c_source_files.append(.{
131 .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{131 .src_path = try comp.dirs.zig_lib.join(arena, &.{
132 "libc", "mingw", dep,132 "libc", "mingw", dep,
133 }),133 }),
134 .extra_flags = crt_args.items,134 .extra_flags = crt_args.items,
...@@ -137,7 +137,7 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre...@@ -137,7 +137,7 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre
137 }137 }
138 for (mingw32_arm64_src) |dep| {138 for (mingw32_arm64_src) |dep| {
139 try c_source_files.append(.{139 try c_source_files.append(.{
140 .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{140 .src_path = try comp.dirs.zig_lib.join(arena, &.{
141 "libc", "mingw", dep,141 "libc", "mingw", dep,
142 }),142 }),
143 .extra_flags = crt_args.items,143 .extra_flags = crt_args.items,
...@@ -164,7 +164,7 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre...@@ -164,7 +164,7 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre
164164
165 for (mingw32_winpthreads_src) |dep| {165 for (mingw32_winpthreads_src) |dep| {
166 try c_source_files.append(.{166 try c_source_files.append(.{
167 .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{167 .src_path = try comp.dirs.zig_lib.join(arena, &.{
168 "libc", "mingw", dep,168 "libc", "mingw", dep,
169 }),169 }),
170 .extra_flags = winpthreads_args.items,170 .extra_flags = winpthreads_args.items,
...@@ -192,7 +192,7 @@ fn addCcArgs(...@@ -192,7 +192,7 @@ fn addCcArgs(
192 "-D__USE_MINGW_ANSI_STDIO=0",192 "-D__USE_MINGW_ANSI_STDIO=0",
193193
194 "-isystem",194 "-isystem",
195 try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libc", "include", "any-windows-any" }),195 try comp.dirs.zig_lib.join(arena, &.{ "libc", "include", "any-windows-any" }),
196 });196 });
197}197}
198198
...@@ -219,7 +219,7 @@ fn addCrtCcArgs(...@@ -219,7 +219,7 @@ fn addCrtCcArgs(
219 "-DHAVE_CONFIG_H",219 "-DHAVE_CONFIG_H",
220220
221 "-I",221 "-I",
222 try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libc", "mingw", "include" }),222 try comp.dirs.zig_lib.join(arena, &.{ "libc", "mingw", "include" }),
223 });223 });
224}224}
225225
...@@ -232,7 +232,7 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void {...@@ -232,7 +232,7 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void {
232 defer arena_allocator.deinit();232 defer arena_allocator.deinit();
233 const arena = arena_allocator.allocator();233 const arena = arena_allocator.allocator();
234234
235 const def_file_path = findDef(arena, comp.getTarget(), comp.zig_lib_directory, lib_name) catch |err| switch (err) {235 const def_file_path = findDef(arena, comp.getTarget(), comp.dirs.zig_lib, lib_name) catch |err| switch (err) {
236 error.FileNotFound => {236 error.FileNotFound => {
237 log.debug("no {s}.def file available to make a DLL import {s}.lib", .{ lib_name, lib_name });237 log.debug("no {s}.def file available to make a DLL import {s}.lib", .{ lib_name, lib_name });
238 // In this case we will end up putting foo.lib onto the linker line and letting the linker238 // In this case we will end up putting foo.lib onto the linker line and letting the linker
...@@ -247,15 +247,15 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void {...@@ -247,15 +247,15 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void {
247 // Use the global cache directory.247 // Use the global cache directory.
248 var cache: Cache = .{248 var cache: Cache = .{
249 .gpa = gpa,249 .gpa = gpa,
250 .manifest_dir = try comp.global_cache_directory.handle.makeOpenPath("h", .{}),250 .manifest_dir = try comp.dirs.global_cache.handle.makeOpenPath("h", .{}),
251 };251 };
252 cache.addPrefix(.{ .path = null, .handle = std.fs.cwd() });252 cache.addPrefix(.{ .path = null, .handle = std.fs.cwd() });
253 cache.addPrefix(comp.zig_lib_directory);253 cache.addPrefix(comp.dirs.zig_lib);
254 cache.addPrefix(comp.global_cache_directory);254 cache.addPrefix(comp.dirs.global_cache);
255 defer cache.manifest_dir.close();255 defer cache.manifest_dir.close();
256256
257 cache.hash.addBytes(build_options.version);257 cache.hash.addBytes(build_options.version);
258 cache.hash.addOptionalBytes(comp.zig_lib_directory.path);258 cache.hash.addOptionalBytes(comp.dirs.zig_lib.path);
259 cache.hash.add(target.cpu.arch);259 cache.hash.add(target.cpu.arch);
260260
261 var man = cache.obtain();261 var man = cache.obtain();
...@@ -276,7 +276,7 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void {...@@ -276,7 +276,7 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void {
276 try comp.crt_files.ensureUnusedCapacity(gpa, 1);276 try comp.crt_files.ensureUnusedCapacity(gpa, 1);
277 comp.crt_files.putAssumeCapacityNoClobber(final_lib_basename, .{277 comp.crt_files.putAssumeCapacityNoClobber(final_lib_basename, .{
278 .full_object_path = .{278 .full_object_path = .{
279 .root_dir = comp.global_cache_directory,279 .root_dir = comp.dirs.global_cache,
280 .sub_path = sub_path,280 .sub_path = sub_path,
281 },281 },
282 .lock = man.toOwnedLock(),282 .lock = man.toOwnedLock(),
...@@ -286,11 +286,11 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void {...@@ -286,11 +286,11 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void {
286286
287 const digest = man.final();287 const digest = man.final();
288 const o_sub_path = try std.fs.path.join(arena, &[_][]const u8{ "o", &digest });288 const o_sub_path = try std.fs.path.join(arena, &[_][]const u8{ "o", &digest });
289 var o_dir = try comp.global_cache_directory.handle.makeOpenPath(o_sub_path, .{});289 var o_dir = try comp.dirs.global_cache.handle.makeOpenPath(o_sub_path, .{});
290 defer o_dir.close();290 defer o_dir.close();
291291
292 const final_def_basename = try std.fmt.allocPrint(arena, "{s}.def", .{lib_name});292 const final_def_basename = try std.fmt.allocPrint(arena, "{s}.def", .{lib_name});
293 const def_final_path = try comp.global_cache_directory.join(arena, &[_][]const u8{293 const def_final_path = try comp.dirs.global_cache.join(arena, &[_][]const u8{
294 "o", &digest, final_def_basename,294 "o", &digest, final_def_basename,
295 });295 });
296296
...@@ -306,7 +306,7 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void {...@@ -306,7 +306,7 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void {
306 var aro_comp = aro.Compilation.init(gpa, std.fs.cwd());306 var aro_comp = aro.Compilation.init(gpa, std.fs.cwd());
307 defer aro_comp.deinit();307 defer aro_comp.deinit();
308308
309 const include_dir = try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libc", "mingw", "def-include" });309 const include_dir = try comp.dirs.zig_lib.join(arena, &.{ "libc", "mingw", "def-include" });
310310
311 if (comp.verbose_cc) print: {311 if (comp.verbose_cc) print: {
312 std.debug.lockStdErr();312 std.debug.lockStdErr();
...@@ -350,7 +350,7 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void {...@@ -350,7 +350,7 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void {
350 if (!build_options.have_llvm) return error.ZigCompilerNotBuiltWithLLVMExtensions;350 if (!build_options.have_llvm) return error.ZigCompilerNotBuiltWithLLVMExtensions;
351 const llvm_bindings = @import("../codegen/llvm/bindings.zig");351 const llvm_bindings = @import("../codegen/llvm/bindings.zig");
352 const def_final_path_z = try arena.dupeZ(u8, def_final_path);352 const def_final_path_z = try arena.dupeZ(u8, def_final_path);
353 const lib_final_path_z = try comp.global_cache_directory.joinZ(arena, &.{lib_final_path});353 const lib_final_path_z = try comp.dirs.global_cache.joinZ(arena, &.{lib_final_path});
354 if (llvm_bindings.WriteImportLibrary(354 if (llvm_bindings.WriteImportLibrary(
355 def_final_path_z.ptr,355 def_final_path_z.ptr,
356 @intFromEnum(target.toCoffMachine()),356 @intFromEnum(target.toCoffMachine()),
...@@ -370,7 +370,7 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void {...@@ -370,7 +370,7 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void {
370 defer comp.mutex.unlock();370 defer comp.mutex.unlock();
371 try comp.crt_files.putNoClobber(gpa, final_lib_basename, .{371 try comp.crt_files.putNoClobber(gpa, final_lib_basename, .{
372 .full_object_path = .{372 .full_object_path = .{
373 .root_dir = comp.global_cache_directory,373 .root_dir = comp.dirs.global_cache,
374 .sub_path = lib_final_path,374 .sub_path = lib_final_path,
375 },375 },
376 .lock = man.toOwnedLock(),376 .lock = man.toOwnedLock(),
src/libs/musl.zig+16-21
...@@ -34,7 +34,7 @@ pub fn buildCrtFile(comp: *Compilation, in_crt_file: CrtFile, prog_node: std.Pro...@@ -34,7 +34,7 @@ pub fn buildCrtFile(comp: *Compilation, in_crt_file: CrtFile, prog_node: std.Pro
34 try args.append("-DCRT");34 try args.append("-DCRT");
35 var files = [_]Compilation.CSourceFile{35 var files = [_]Compilation.CSourceFile{
36 .{36 .{
37 .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{37 .src_path = try comp.dirs.zig_lib.join(arena, &.{
38 "libc", "musl", "crt", "crt1.c",38 "libc", "musl", "crt", "crt1.c",
39 }),39 }),
40 .extra_flags = args.items,40 .extra_flags = args.items,
...@@ -54,7 +54,7 @@ pub fn buildCrtFile(comp: *Compilation, in_crt_file: CrtFile, prog_node: std.Pro...@@ -54,7 +54,7 @@ pub fn buildCrtFile(comp: *Compilation, in_crt_file: CrtFile, prog_node: std.Pro
54 try args.append("-DCRT");54 try args.append("-DCRT");
55 var files = [_]Compilation.CSourceFile{55 var files = [_]Compilation.CSourceFile{
56 .{56 .{
57 .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{57 .src_path = try comp.dirs.zig_lib.join(arena, &.{
58 "libc", "musl", "crt", "rcrt1.c",58 "libc", "musl", "crt", "rcrt1.c",
59 }),59 }),
60 .extra_flags = args.items,60 .extra_flags = args.items,
...@@ -75,7 +75,7 @@ pub fn buildCrtFile(comp: *Compilation, in_crt_file: CrtFile, prog_node: std.Pro...@@ -75,7 +75,7 @@ pub fn buildCrtFile(comp: *Compilation, in_crt_file: CrtFile, prog_node: std.Pro
75 try args.append("-DCRT");75 try args.append("-DCRT");
76 var files = [_]Compilation.CSourceFile{76 var files = [_]Compilation.CSourceFile{
77 .{77 .{
78 .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{78 .src_path = try comp.dirs.zig_lib.join(arena, &.{
79 "libc", "musl", "crt", "Scrt1.c",79 "libc", "musl", "crt", "Scrt1.c",
80 }),80 }),
81 .extra_flags = args.items,81 .extra_flags = args.items,
...@@ -165,7 +165,7 @@ pub fn buildCrtFile(comp: *Compilation, in_crt_file: CrtFile, prog_node: std.Pro...@@ -165,7 +165,7 @@ pub fn buildCrtFile(comp: *Compilation, in_crt_file: CrtFile, prog_node: std.Pro
165 try addCcArgs(comp, arena, &args, ext == .o3);165 try addCcArgs(comp, arena, &args, ext == .o3);
166 const c_source_file = try c_source_files.addOne();166 const c_source_file = try c_source_files.addOne();
167 c_source_file.* = .{167 c_source_file.* = .{
168 .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libc", src_file }),168 .src_path = try comp.dirs.zig_lib.join(arena, &.{ "libc", src_file }),
169 .extra_flags = args.items,169 .extra_flags = args.items,
170 .owner = undefined,170 .owner = undefined,
171 };171 };
...@@ -220,9 +220,8 @@ pub fn buildCrtFile(comp: *Compilation, in_crt_file: CrtFile, prog_node: std.Pro...@@ -220,9 +220,8 @@ pub fn buildCrtFile(comp: *Compilation, in_crt_file: CrtFile, prog_node: std.Pro
220 &.{ arch_define, family_define };220 &.{ arch_define, family_define };
221221
222 const root_mod = try Module.create(arena, .{222 const root_mod = try Module.create(arena, .{
223 .global_cache_directory = comp.global_cache_directory,
224 .paths = .{223 .paths = .{
225 .root = .{ .root_dir = comp.zig_lib_directory },224 .root = .zig_lib_root,
226 .root_src_path = "",225 .root_src_path = "",
227 },226 },
228 .fully_qualified_name = "root",227 .fully_qualified_name = "root",
...@@ -242,14 +241,10 @@ pub fn buildCrtFile(comp: *Compilation, in_crt_file: CrtFile, prog_node: std.Pro...@@ -242,14 +241,10 @@ pub fn buildCrtFile(comp: *Compilation, in_crt_file: CrtFile, prog_node: std.Pro
242 .global = config,241 .global = config,
243 .cc_argv = cc_argv,242 .cc_argv = cc_argv,
244 .parent = null,243 .parent = null,
245 .builtin_mod = null,
246 .builtin_modules = null, // there is only one module in this compilation
247 });244 });
248245
249 const sub_compilation = try Compilation.create(comp.gpa, arena, .{246 const sub_compilation = try Compilation.create(comp.gpa, arena, .{
250 .local_cache_directory = comp.global_cache_directory,247 .dirs = comp.dirs.withoutLocalCache(),
251 .global_cache_directory = comp.global_cache_directory,
252 .zig_lib_directory = comp.zig_lib_directory,
253 .self_exe_path = comp.self_exe_path,248 .self_exe_path = comp.self_exe_path,
254 .cache_mode = .whole,249 .cache_mode = .whole,
255 .config = config,250 .config = config,
...@@ -266,9 +261,9 @@ pub fn buildCrtFile(comp: *Compilation, in_crt_file: CrtFile, prog_node: std.Pro...@@ -266,9 +261,9 @@ pub fn buildCrtFile(comp: *Compilation, in_crt_file: CrtFile, prog_node: std.Pro
266 .verbose_cimport = comp.verbose_cimport,261 .verbose_cimport = comp.verbose_cimport,
267 .verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features,262 .verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features,
268 .clang_passthrough_mode = comp.clang_passthrough_mode,263 .clang_passthrough_mode = comp.clang_passthrough_mode,
269 .c_source_files = &[_]Compilation.CSourceFile{264 .c_source_files = &.{
270 .{265 .{
271 .src_path = try comp.zig_lib_directory.join(arena, &.{ "libc", "musl", "libc.S" }),266 .src_path = try comp.dirs.zig_lib.join(arena, &.{ "libc", "musl", "libc.S" }),
272 .owner = root_mod,267 .owner = root_mod,
273 },268 },
274 },269 },
...@@ -411,25 +406,25 @@ fn addCcArgs(...@@ -411,25 +406,25 @@ fn addCcArgs(
411 "-D_XOPEN_SOURCE=700",406 "-D_XOPEN_SOURCE=700",
412407
413 "-I",408 "-I",
414 try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libc", "musl", "arch", arch_name }),409 try comp.dirs.zig_lib.join(arena, &.{ "libc", "musl", "arch", arch_name }),
415410
416 "-I",411 "-I",
417 try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libc", "musl", "arch", "generic" }),412 try comp.dirs.zig_lib.join(arena, &.{ "libc", "musl", "arch", "generic" }),
418413
419 "-I",414 "-I",
420 try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libc", "musl", "src", "include" }),415 try comp.dirs.zig_lib.join(arena, &.{ "libc", "musl", "src", "include" }),
421416
422 "-I",417 "-I",
423 try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libc", "musl", "src", "internal" }),418 try comp.dirs.zig_lib.join(arena, &.{ "libc", "musl", "src", "internal" }),
424419
425 "-I",420 "-I",
426 try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libc", "musl", "include" }),421 try comp.dirs.zig_lib.join(arena, &.{ "libc", "musl", "include" }),
427422
428 "-I",423 "-I",
429 try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libc", "include", triple }),424 try comp.dirs.zig_lib.join(arena, &.{ "libc", "include", triple }),
430425
431 "-I",426 "-I",
432 try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libc", "include", "generic-musl" }),427 try comp.dirs.zig_lib.join(arena, &.{ "libc", "include", "generic-musl" }),
433428
434 o_arg,429 o_arg,
435430
...@@ -444,7 +439,7 @@ fn addCcArgs(...@@ -444,7 +439,7 @@ fn addCcArgs(
444439
445fn start_asm_path(comp: *Compilation, arena: Allocator, basename: []const u8) ![]const u8 {440fn start_asm_path(comp: *Compilation, arena: Allocator, basename: []const u8) ![]const u8 {
446 const target = comp.getTarget();441 const target = comp.getTarget();
447 return comp.zig_lib_directory.join(arena, &[_][]const u8{442 return comp.dirs.zig_lib.join(arena, &.{
448 "libc", "musl", "crt", std.zig.target.muslArchName(target.cpu.arch, target.abi), basename,443 "libc", "musl", "crt", std.zig.target.muslArchName(target.cpu.arch, target.abi), basename,
449 });444 });
450}445}
src/libs/wasi_libc.zig+27-27
...@@ -81,7 +81,7 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre...@@ -81,7 +81,7 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre
81 try addLibcBottomHalfIncludes(comp, arena, &args);81 try addLibcBottomHalfIncludes(comp, arena, &args);
82 var files = [_]Compilation.CSourceFile{82 var files = [_]Compilation.CSourceFile{
83 .{83 .{
84 .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{84 .src_path = try comp.dirs.zig_lib.join(arena, &.{
85 "libc", try sanitize(arena, crt1_reactor_src_file),85 "libc", try sanitize(arena, crt1_reactor_src_file),
86 }),86 }),
87 .extra_flags = args.items,87 .extra_flags = args.items,
...@@ -96,7 +96,7 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre...@@ -96,7 +96,7 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre
96 try addLibcBottomHalfIncludes(comp, arena, &args);96 try addLibcBottomHalfIncludes(comp, arena, &args);
97 var files = [_]Compilation.CSourceFile{97 var files = [_]Compilation.CSourceFile{
98 .{98 .{
99 .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{99 .src_path = try comp.dirs.zig_lib.join(arena, &.{
100 "libc", try sanitize(arena, crt1_command_src_file),100 "libc", try sanitize(arena, crt1_command_src_file),
101 }),101 }),
102 .extra_flags = args.items,102 .extra_flags = args.items,
...@@ -114,7 +114,7 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre...@@ -114,7 +114,7 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre
114 try addCCArgs(comp, arena, &args, .{ .want_O3 = true, .no_strict_aliasing = true });114 try addCCArgs(comp, arena, &args, .{ .want_O3 = true, .no_strict_aliasing = true });
115 for (emmalloc_src_files) |file_path| {115 for (emmalloc_src_files) |file_path| {
116 try libc_sources.append(.{116 try libc_sources.append(.{
117 .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{117 .src_path = try comp.dirs.zig_lib.join(arena, &.{
118 "libc", try sanitize(arena, file_path),118 "libc", try sanitize(arena, file_path),
119 }),119 }),
120 .extra_flags = args.items,120 .extra_flags = args.items,
...@@ -131,7 +131,7 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre...@@ -131,7 +131,7 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre
131131
132 for (libc_bottom_half_src_files) |file_path| {132 for (libc_bottom_half_src_files) |file_path| {
133 try libc_sources.append(.{133 try libc_sources.append(.{
134 .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{134 .src_path = try comp.dirs.zig_lib.join(arena, &.{
135 "libc", try sanitize(arena, file_path),135 "libc", try sanitize(arena, file_path),
136 }),136 }),
137 .extra_flags = args.items,137 .extra_flags = args.items,
...@@ -148,7 +148,7 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre...@@ -148,7 +148,7 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre
148148
149 for (libc_top_half_src_files) |file_path| {149 for (libc_top_half_src_files) |file_path| {
150 try libc_sources.append(.{150 try libc_sources.append(.{
151 .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{151 .src_path = try comp.dirs.zig_lib.join(arena, &.{
152 "libc", try sanitize(arena, file_path),152 "libc", try sanitize(arena, file_path),
153 }),153 }),
154 .extra_flags = args.items,154 .extra_flags = args.items,
...@@ -168,7 +168,7 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre...@@ -168,7 +168,7 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre
168 var emu_dl_sources = std.ArrayList(Compilation.CSourceFile).init(arena);168 var emu_dl_sources = std.ArrayList(Compilation.CSourceFile).init(arena);
169 for (emulated_dl_src_files) |file_path| {169 for (emulated_dl_src_files) |file_path| {
170 try emu_dl_sources.append(.{170 try emu_dl_sources.append(.{
171 .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{171 .src_path = try comp.dirs.zig_lib.join(arena, &.{
172 "libc", try sanitize(arena, file_path),172 "libc", try sanitize(arena, file_path),
173 }),173 }),
174 .extra_flags = args.items,174 .extra_flags = args.items,
...@@ -186,7 +186,7 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre...@@ -186,7 +186,7 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre
186 var emu_clocks_sources = std.ArrayList(Compilation.CSourceFile).init(arena);186 var emu_clocks_sources = std.ArrayList(Compilation.CSourceFile).init(arena);
187 for (emulated_process_clocks_src_files) |file_path| {187 for (emulated_process_clocks_src_files) |file_path| {
188 try emu_clocks_sources.append(.{188 try emu_clocks_sources.append(.{
189 .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{189 .src_path = try comp.dirs.zig_lib.join(arena, &.{
190 "libc", try sanitize(arena, file_path),190 "libc", try sanitize(arena, file_path),
191 }),191 }),
192 .extra_flags = args.items,192 .extra_flags = args.items,
...@@ -203,7 +203,7 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre...@@ -203,7 +203,7 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre
203 var emu_getpid_sources = std.ArrayList(Compilation.CSourceFile).init(arena);203 var emu_getpid_sources = std.ArrayList(Compilation.CSourceFile).init(arena);
204 for (emulated_getpid_src_files) |file_path| {204 for (emulated_getpid_src_files) |file_path| {
205 try emu_getpid_sources.append(.{205 try emu_getpid_sources.append(.{
206 .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{206 .src_path = try comp.dirs.zig_lib.join(arena, &.{
207 "libc", try sanitize(arena, file_path),207 "libc", try sanitize(arena, file_path),
208 }),208 }),
209 .extra_flags = args.items,209 .extra_flags = args.items,
...@@ -220,7 +220,7 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre...@@ -220,7 +220,7 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre
220 var emu_mman_sources = std.ArrayList(Compilation.CSourceFile).init(arena);220 var emu_mman_sources = std.ArrayList(Compilation.CSourceFile).init(arena);
221 for (emulated_mman_src_files) |file_path| {221 for (emulated_mman_src_files) |file_path| {
222 try emu_mman_sources.append(.{222 try emu_mman_sources.append(.{
223 .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{223 .src_path = try comp.dirs.zig_lib.join(arena, &.{
224 "libc", try sanitize(arena, file_path),224 "libc", try sanitize(arena, file_path),
225 }),225 }),
226 .extra_flags = args.items,226 .extra_flags = args.items,
...@@ -238,7 +238,7 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre...@@ -238,7 +238,7 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre
238238
239 for (emulated_signal_bottom_half_src_files) |file_path| {239 for (emulated_signal_bottom_half_src_files) |file_path| {
240 try emu_signal_sources.append(.{240 try emu_signal_sources.append(.{
241 .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{241 .src_path = try comp.dirs.zig_lib.join(arena, &.{
242 "libc", try sanitize(arena, file_path),242 "libc", try sanitize(arena, file_path),
243 }),243 }),
244 .extra_flags = args.items,244 .extra_flags = args.items,
...@@ -255,7 +255,7 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre...@@ -255,7 +255,7 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre
255255
256 for (emulated_signal_top_half_src_files) |file_path| {256 for (emulated_signal_top_half_src_files) |file_path| {
257 try emu_signal_sources.append(.{257 try emu_signal_sources.append(.{
258 .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{258 .src_path = try comp.dirs.zig_lib.join(arena, &.{
259 "libc", try sanitize(arena, file_path),259 "libc", try sanitize(arena, file_path),
260 }),260 }),
261 .extra_flags = args.items,261 .extra_flags = args.items,
...@@ -316,10 +316,10 @@ fn addCCArgs(...@@ -316,10 +316,10 @@ fn addCCArgs(
316 "/",316 "/",
317317
318 "-iwithsysroot",318 "-iwithsysroot",
319 try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libc", "include", triple }),319 try comp.dirs.zig_lib.join(arena, &.{ "libc", "include", triple }),
320320
321 "-iwithsysroot",321 "-iwithsysroot",
322 try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libc", "include", "generic-musl" }),322 try comp.dirs.zig_lib.join(arena, &.{ "libc", "include", "generic-musl" }),
323323
324 "-DBULK_MEMORY_THRESHOLD=32",324 "-DBULK_MEMORY_THRESHOLD=32",
325 });325 });
...@@ -336,7 +336,7 @@ fn addLibcBottomHalfIncludes(...@@ -336,7 +336,7 @@ fn addLibcBottomHalfIncludes(
336) error{OutOfMemory}!void {336) error{OutOfMemory}!void {
337 try args.appendSlice(&[_][]const u8{337 try args.appendSlice(&[_][]const u8{
338 "-I",338 "-I",
339 try comp.zig_lib_directory.join(arena, &[_][]const u8{339 try comp.dirs.zig_lib.join(arena, &.{
340 "libc",340 "libc",
341 "wasi",341 "wasi",
342 "libc-bottom-half",342 "libc-bottom-half",
...@@ -345,7 +345,7 @@ fn addLibcBottomHalfIncludes(...@@ -345,7 +345,7 @@ fn addLibcBottomHalfIncludes(
345 }),345 }),
346346
347 "-I",347 "-I",
348 try comp.zig_lib_directory.join(arena, &[_][]const u8{348 try comp.dirs.zig_lib.join(arena, &.{
349 "libc",349 "libc",
350 "wasi",350 "wasi",
351 "libc-bottom-half",351 "libc-bottom-half",
...@@ -355,7 +355,7 @@ fn addLibcBottomHalfIncludes(...@@ -355,7 +355,7 @@ fn addLibcBottomHalfIncludes(
355 }),355 }),
356356
357 "-I",357 "-I",
358 try comp.zig_lib_directory.join(arena, &[_][]const u8{358 try comp.dirs.zig_lib.join(arena, &.{
359 "libc",359 "libc",
360 "wasi",360 "wasi",
361 "libc-bottom-half",361 "libc-bottom-half",
...@@ -364,7 +364,7 @@ fn addLibcBottomHalfIncludes(...@@ -364,7 +364,7 @@ fn addLibcBottomHalfIncludes(
364 }),364 }),
365365
366 "-I",366 "-I",
367 try comp.zig_lib_directory.join(arena, &[_][]const u8{367 try comp.dirs.zig_lib.join(arena, &.{
368 "libc",368 "libc",
369 "wasi",369 "wasi",
370 "libc-top-half",370 "libc-top-half",
...@@ -374,7 +374,7 @@ fn addLibcBottomHalfIncludes(...@@ -374,7 +374,7 @@ fn addLibcBottomHalfIncludes(
374 }),374 }),
375375
376 "-I",376 "-I",
377 try comp.zig_lib_directory.join(arena, &[_][]const u8{377 try comp.dirs.zig_lib.join(arena, &.{
378 "libc",378 "libc",
379 "musl",379 "musl",
380 "src",380 "src",
...@@ -382,7 +382,7 @@ fn addLibcBottomHalfIncludes(...@@ -382,7 +382,7 @@ fn addLibcBottomHalfIncludes(
382 }),382 }),
383383
384 "-I",384 "-I",
385 try comp.zig_lib_directory.join(arena, &[_][]const u8{385 try comp.dirs.zig_lib.join(arena, &.{
386 "libc",386 "libc",
387 "wasi",387 "wasi",
388 "libc-top-half",388 "libc-top-half",
...@@ -392,7 +392,7 @@ fn addLibcBottomHalfIncludes(...@@ -392,7 +392,7 @@ fn addLibcBottomHalfIncludes(
392 }),392 }),
393393
394 "-I",394 "-I",
395 try comp.zig_lib_directory.join(arena, &[_][]const u8{395 try comp.dirs.zig_lib.join(arena, &.{
396 "libc",396 "libc",
397 "musl",397 "musl",
398 "src",398 "src",
...@@ -408,7 +408,7 @@ fn addLibcTopHalfIncludes(...@@ -408,7 +408,7 @@ fn addLibcTopHalfIncludes(
408) error{OutOfMemory}!void {408) error{OutOfMemory}!void {
409 try args.appendSlice(&[_][]const u8{409 try args.appendSlice(&[_][]const u8{
410 "-I",410 "-I",
411 try comp.zig_lib_directory.join(arena, &[_][]const u8{411 try comp.dirs.zig_lib.join(arena, &.{
412 "libc",412 "libc",
413 "wasi",413 "wasi",
414 "libc-top-half",414 "libc-top-half",
...@@ -418,7 +418,7 @@ fn addLibcTopHalfIncludes(...@@ -418,7 +418,7 @@ fn addLibcTopHalfIncludes(
418 }),418 }),
419419
420 "-I",420 "-I",
421 try comp.zig_lib_directory.join(arena, &[_][]const u8{421 try comp.dirs.zig_lib.join(arena, &.{
422 "libc",422 "libc",
423 "musl",423 "musl",
424 "src",424 "src",
...@@ -426,7 +426,7 @@ fn addLibcTopHalfIncludes(...@@ -426,7 +426,7 @@ fn addLibcTopHalfIncludes(
426 }),426 }),
427427
428 "-I",428 "-I",
429 try comp.zig_lib_directory.join(arena, &[_][]const u8{429 try comp.dirs.zig_lib.join(arena, &.{
430 "libc",430 "libc",
431 "wasi",431 "wasi",
432 "libc-top-half",432 "libc-top-half",
...@@ -436,7 +436,7 @@ fn addLibcTopHalfIncludes(...@@ -436,7 +436,7 @@ fn addLibcTopHalfIncludes(
436 }),436 }),
437437
438 "-I",438 "-I",
439 try comp.zig_lib_directory.join(arena, &[_][]const u8{439 try comp.dirs.zig_lib.join(arena, &.{
440 "libc",440 "libc",
441 "musl",441 "musl",
442 "src",442 "src",
...@@ -444,7 +444,7 @@ fn addLibcTopHalfIncludes(...@@ -444,7 +444,7 @@ fn addLibcTopHalfIncludes(
444 }),444 }),
445445
446 "-I",446 "-I",
447 try comp.zig_lib_directory.join(arena, &[_][]const u8{447 try comp.dirs.zig_lib.join(arena, &.{
448 "libc",448 "libc",
449 "wasi",449 "wasi",
450 "libc-top-half",450 "libc-top-half",
...@@ -454,7 +454,7 @@ fn addLibcTopHalfIncludes(...@@ -454,7 +454,7 @@ fn addLibcTopHalfIncludes(
454 }),454 }),
455455
456 "-I",456 "-I",
457 try comp.zig_lib_directory.join(arena, &[_][]const u8{457 try comp.dirs.zig_lib.join(arena, &.{
458 "libc",458 "libc",
459 "musl",459 "musl",
460 "arch",460 "arch",
...@@ -462,7 +462,7 @@ fn addLibcTopHalfIncludes(...@@ -462,7 +462,7 @@ fn addLibcTopHalfIncludes(
462 }),462 }),
463463
464 "-I",464 "-I",
465 try comp.zig_lib_directory.join(arena, &[_][]const u8{465 try comp.dirs.zig_lib.join(arena, &.{
466 "libc",466 "libc",
467 "wasi",467 "wasi",
468 "libc-top-half",468 "libc-top-half",
src/link.zig+3-3
...@@ -1675,8 +1675,8 @@ pub fn spawnLld(...@@ -1675,8 +1675,8 @@ pub fn spawnLld(
1675 const rand_int = std.crypto.random.int(u64);1675 const rand_int = std.crypto.random.int(u64);
1676 const rsp_path = "tmp" ++ s ++ std.fmt.hex(rand_int) ++ ".rsp";1676 const rsp_path = "tmp" ++ s ++ std.fmt.hex(rand_int) ++ ".rsp";
16771677
1678 const rsp_file = try comp.local_cache_directory.handle.createFileZ(rsp_path, .{});1678 const rsp_file = try comp.dirs.local_cache.handle.createFileZ(rsp_path, .{});
1679 defer comp.local_cache_directory.handle.deleteFileZ(rsp_path) catch |err|1679 defer comp.dirs.local_cache.handle.deleteFileZ(rsp_path) catch |err|
1680 log.warn("failed to delete response file {s}: {s}", .{ rsp_path, @errorName(err) });1680 log.warn("failed to delete response file {s}: {s}", .{ rsp_path, @errorName(err) });
1681 {1681 {
1682 defer rsp_file.close();1682 defer rsp_file.close();
...@@ -1700,7 +1700,7 @@ pub fn spawnLld(...@@ -1700,7 +1700,7 @@ pub fn spawnLld(
1700 var rsp_child = std.process.Child.init(&.{ argv[0], argv[1], try std.fmt.allocPrint(1700 var rsp_child = std.process.Child.init(&.{ argv[0], argv[1], try std.fmt.allocPrint(
1701 arena,1701 arena,
1702 "@{s}",1702 "@{s}",
1703 .{try comp.local_cache_directory.join(arena, &.{rsp_path})},1703 .{try comp.dirs.local_cache.join(arena, &.{rsp_path})},
1704 ) }, arena);1704 ) }, arena);
1705 if (comp.clang_passthrough_mode) {1705 if (comp.clang_passthrough_mode) {
1706 rsp_child.stdin_behavior = .Inherit;1706 rsp_child.stdin_behavior = .Inherit;
src/link/C.zig+4-4
...@@ -206,7 +206,7 @@ pub fn updateFunc(...@@ -206,7 +206,7 @@ pub fn updateFunc(
206 .dg = .{206 .dg = .{
207 .gpa = gpa,207 .gpa = gpa,
208 .pt = pt,208 .pt = pt,
209 .mod = zcu.navFileScope(func.owner_nav).mod,209 .mod = zcu.navFileScope(func.owner_nav).mod.?,
210 .error_msg = null,210 .error_msg = null,
211 .pass = .{ .nav = func.owner_nav },211 .pass = .{ .nav = func.owner_nav },
212 .is_naked_fn = Type.fromInterned(func.ty).fnCallingConvention(zcu) == .naked,212 .is_naked_fn = Type.fromInterned(func.ty).fnCallingConvention(zcu) == .naked,
...@@ -337,7 +337,7 @@ pub fn updateNav(self: *C, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) l...@@ -337,7 +337,7 @@ pub fn updateNav(self: *C, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) l
337 .dg = .{337 .dg = .{
338 .gpa = gpa,338 .gpa = gpa,
339 .pt = pt,339 .pt = pt,
340 .mod = zcu.navFileScope(nav_index).mod,340 .mod = zcu.navFileScope(nav_index).mod.?,
341 .error_msg = null,341 .error_msg = null,
342 .pass = .{ .nav = nav_index },342 .pass = .{ .nav = nav_index },
343 .is_naked_fn = false,343 .is_naked_fn = false,
...@@ -490,7 +490,7 @@ pub fn flushModule(self: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node:...@@ -490,7 +490,7 @@ pub fn flushModule(self: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node:
490490
491 for (self.navs.keys(), self.navs.values()) |nav, *av_block| try self.flushAvBlock(491 for (self.navs.keys(), self.navs.values()) |nav, *av_block| try self.flushAvBlock(
492 pt,492 pt,
493 zcu.navFileScope(nav).mod,493 zcu.navFileScope(nav).mod.?,
494 &f,494 &f,
495 av_block,495 av_block,
496 self.exported_navs.getPtr(nav),496 self.exported_navs.getPtr(nav),
...@@ -846,7 +846,7 @@ pub fn updateExports(...@@ -846,7 +846,7 @@ pub fn updateExports(
846 const gpa = zcu.gpa;846 const gpa = zcu.gpa;
847 const mod, const pass: codegen.DeclGen.Pass, const decl_block, const exported_block = switch (exported) {847 const mod, const pass: codegen.DeclGen.Pass, const decl_block, const exported_block = switch (exported) {
848 .nav => |nav| .{848 .nav => |nav| .{
849 zcu.navFileScope(nav).mod,849 zcu.navFileScope(nav).mod.?,
850 .{ .nav = nav },850 .{ .nav = nav },
851 self.navs.getPtr(nav).?,851 self.navs.getPtr(nav).?,
852 (try self.exported_navs.getOrPut(gpa, nav)).value_ptr,852 (try self.exported_navs.getOrPut(gpa, nav)).value_ptr,
src/link/Coff.zig+1-1
...@@ -1392,7 +1392,7 @@ fn updateNavCode(...@@ -1392,7 +1392,7 @@ fn updateNavCode(
13921392
1393 log.debug("updateNavCode {} 0x{x}", .{ nav.fqn.fmt(ip), nav_index });1393 log.debug("updateNavCode {} 0x{x}", .{ nav.fqn.fmt(ip), nav_index });
13941394
1395 const target = zcu.navFileScope(nav_index).mod.resolved_target.result;1395 const target = zcu.navFileScope(nav_index).mod.?.resolved_target.result;
1396 const required_alignment = switch (pt.navAlignment(nav_index)) {1396 const required_alignment = switch (pt.navAlignment(nav_index)) {
1397 .none => target_util.defaultFunctionAlignment(target),1397 .none => target_util.defaultFunctionAlignment(target),
1398 else => |a| a.maxStrict(target_util.minFunctionAlignment(target)),1398 else => |a| a.maxStrict(target_util.minFunctionAlignment(target)),
src/link/Dwarf.zig+17-27
...@@ -34,9 +34,7 @@ pub const UpdateError = error{...@@ -34,9 +34,7 @@ pub const UpdateError = error{
34 std.fs.File.PReadError ||34 std.fs.File.PReadError ||
35 std.fs.File.PWriteError;35 std.fs.File.PWriteError;
3636
37pub const FlushError =37pub const FlushError = UpdateError;
38 UpdateError ||
39 std.process.GetCwdError;
4038
41pub const RelocError =39pub const RelocError =
42 std.fs.File.PWriteError;40 std.fs.File.PWriteError;
...@@ -967,7 +965,7 @@ const Entry = struct {...@@ -967,7 +965,7 @@ const Entry = struct {
967 const ip = &zcu.intern_pool;965 const ip = &zcu.intern_pool;
968 for (dwarf.types.keys(), dwarf.types.values()) |ty, other_entry| {966 for (dwarf.types.keys(), dwarf.types.values()) |ty, other_entry| {
969 const ty_unit: Unit.Index = if (Type.fromInterned(ty).typeDeclInst(zcu)) |inst_index|967 const ty_unit: Unit.Index = if (Type.fromInterned(ty).typeDeclInst(zcu)) |inst_index|
970 dwarf.getUnit(zcu.fileByIndex(inst_index.resolveFile(ip)).mod) catch unreachable968 dwarf.getUnit(zcu.fileByIndex(inst_index.resolveFile(ip)).mod.?) catch unreachable
971 else969 else
972 .main;970 .main;
973 if (sec.getUnit(ty_unit) == unit and unit.getEntry(other_entry) == entry)971 if (sec.getUnit(ty_unit) == unit and unit.getEntry(other_entry) == entry)
...@@ -977,7 +975,7 @@ const Entry = struct {...@@ -977,7 +975,7 @@ const Entry = struct {
977 });975 });
978 }976 }
979 for (dwarf.navs.keys(), dwarf.navs.values()) |nav, other_entry| {977 for (dwarf.navs.keys(), dwarf.navs.values()) |nav, other_entry| {
980 const nav_unit = dwarf.getUnit(zcu.fileByIndex(ip.getNav(nav).srcInst(ip).resolveFile(ip)).mod) catch unreachable;978 const nav_unit = dwarf.getUnit(zcu.fileByIndex(ip.getNav(nav).srcInst(ip).resolveFile(ip)).mod.?) catch unreachable;
981 if (sec.getUnit(nav_unit) == unit and unit.getEntry(other_entry) == entry)979 if (sec.getUnit(nav_unit) == unit and unit.getEntry(other_entry) == entry)
982 log.err("missing Nav({}({d}))", .{ ip.getNav(nav).fqn.fmt(ip), @intFromEnum(nav) });980 log.err("missing Nav({}({d}))", .{ ip.getNav(nav).fqn.fmt(ip), @intFromEnum(nav) });
983 }981 }
...@@ -1620,7 +1618,7 @@ pub const WipNav = struct {...@@ -1620,7 +1618,7 @@ pub const WipNav = struct {
16201618
1621 const new_func_info = zcu.funcInfo(func);1619 const new_func_info = zcu.funcInfo(func);
1622 const new_file = zcu.navFileScopeIndex(new_func_info.owner_nav);1620 const new_file = zcu.navFileScopeIndex(new_func_info.owner_nav);
1623 const new_unit = try dwarf.getUnit(zcu.fileByIndex(new_file).mod);1621 const new_unit = try dwarf.getUnit(zcu.fileByIndex(new_file).mod.?);
16241622
1625 const dlw = wip_nav.debug_line.writer(dwarf.gpa);1623 const dlw = wip_nav.debug_line.writer(dwarf.gpa);
1626 if (dwarf.incremental()) {1624 if (dwarf.incremental()) {
...@@ -1810,7 +1808,7 @@ pub const WipNav = struct {...@@ -1810,7 +1808,7 @@ pub const WipNav = struct {
1810 fn getNavEntry(wip_nav: *WipNav, nav_index: InternPool.Nav.Index) UpdateError!struct { Unit.Index, Entry.Index } {1808 fn getNavEntry(wip_nav: *WipNav, nav_index: InternPool.Nav.Index) UpdateError!struct { Unit.Index, Entry.Index } {
1811 const zcu = wip_nav.pt.zcu;1809 const zcu = wip_nav.pt.zcu;
1812 const ip = &zcu.intern_pool;1810 const ip = &zcu.intern_pool;
1813 const unit = try wip_nav.dwarf.getUnit(zcu.fileByIndex(ip.getNav(nav_index).srcInst(ip).resolveFile(ip)).mod);1811 const unit = try wip_nav.dwarf.getUnit(zcu.fileByIndex(ip.getNav(nav_index).srcInst(ip).resolveFile(ip)).mod.?);
1814 const gop = try wip_nav.dwarf.navs.getOrPut(wip_nav.dwarf.gpa, nav_index);1812 const gop = try wip_nav.dwarf.navs.getOrPut(wip_nav.dwarf.gpa, nav_index);
1815 if (gop.found_existing) return .{ unit, gop.value_ptr.* };1813 if (gop.found_existing) return .{ unit, gop.value_ptr.* };
1816 const entry = try wip_nav.dwarf.addCommonEntry(unit);1814 const entry = try wip_nav.dwarf.addCommonEntry(unit);
...@@ -1828,7 +1826,7 @@ pub const WipNav = struct {...@@ -1828,7 +1826,7 @@ pub const WipNav = struct {
1828 const ip = &zcu.intern_pool;1826 const ip = &zcu.intern_pool;
1829 const maybe_inst_index = ty.typeDeclInst(zcu);1827 const maybe_inst_index = ty.typeDeclInst(zcu);
1830 const unit = if (maybe_inst_index) |inst_index|1828 const unit = if (maybe_inst_index) |inst_index|
1831 try wip_nav.dwarf.getUnit(zcu.fileByIndex(inst_index.resolveFile(ip)).mod)1829 try wip_nav.dwarf.getUnit(zcu.fileByIndex(inst_index.resolveFile(ip)).mod.?)
1832 else1830 else
1833 .main;1831 .main;
1834 const gop = try wip_nav.dwarf.types.getOrPut(wip_nav.dwarf.gpa, ty.toIntern());1832 const gop = try wip_nav.dwarf.types.getOrPut(wip_nav.dwarf.gpa, ty.toIntern());
...@@ -2386,7 +2384,7 @@ fn initWipNavInner(...@@ -2386,7 +2384,7 @@ fn initWipNavInner(
2386 else => {},2384 else => {},
2387 }2385 }
23882386
2389 const unit = try dwarf.getUnit(file.mod);2387 const unit = try dwarf.getUnit(file.mod.?);
2390 const nav_gop = try dwarf.navs.getOrPut(dwarf.gpa, nav_index);2388 const nav_gop = try dwarf.navs.getOrPut(dwarf.gpa, nav_index);
2391 errdefer _ = if (!nav_gop.found_existing) dwarf.navs.pop();2389 errdefer _ = if (!nav_gop.found_existing) dwarf.navs.pop();
2392 if (nav_gop.found_existing) {2390 if (nav_gop.found_existing) {
...@@ -2514,7 +2512,7 @@ fn initWipNavInner(...@@ -2514,7 +2512,7 @@ fn initWipNavInner(
2514 try wip_nav.infoAddrSym(sym_index, 0);2512 try wip_nav.infoAddrSym(sym_index, 0);
2515 wip_nav.func_high_pc = @intCast(wip_nav.debug_info.items.len);2513 wip_nav.func_high_pc = @intCast(wip_nav.debug_info.items.len);
2516 try diw.writeInt(u32, 0, dwarf.endian);2514 try diw.writeInt(u32, 0, dwarf.endian);
2517 const target = file.mod.resolved_target.result;2515 const target = file.mod.?.resolved_target.result;
2518 try uleb128(diw, switch (nav.status.fully_resolved.alignment) {2516 try uleb128(diw, switch (nav.status.fully_resolved.alignment) {
2519 .none => target_info.defaultFunctionAlignment(target),2517 .none => target_info.defaultFunctionAlignment(target),
2520 else => |a| a.maxStrict(target_info.minFunctionAlignment(target)),2518 else => |a| a.maxStrict(target_info.minFunctionAlignment(target)),
...@@ -2726,7 +2724,7 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo...@@ -2726,7 +2724,7 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo
2726 var wip_nav: WipNav = .{2724 var wip_nav: WipNav = .{
2727 .dwarf = dwarf,2725 .dwarf = dwarf,
2728 .pt = pt,2726 .pt = pt,
2729 .unit = try dwarf.getUnit(file.mod),2727 .unit = try dwarf.getUnit(file.mod.?),
2730 .entry = undefined,2728 .entry = undefined,
2731 .any_children = false,2729 .any_children = false,
2732 .func = .none,2730 .func = .none,
...@@ -4044,7 +4042,7 @@ pub fn updateContainerType(dwarf: *Dwarf, pt: Zcu.PerThread, type_index: InternP...@@ -4044,7 +4042,7 @@ pub fn updateContainerType(dwarf: *Dwarf, pt: Zcu.PerThread, type_index: InternP
40444042
4045 const inst_info = ty.typeDeclInst(zcu).?.resolveFull(ip).?;4043 const inst_info = ty.typeDeclInst(zcu).?.resolveFull(ip).?;
4046 const file = zcu.fileByIndex(inst_info.file);4044 const file = zcu.fileByIndex(inst_info.file);
4047 const unit = try dwarf.getUnit(file.mod);4045 const unit = try dwarf.getUnit(file.mod.?);
4048 const file_gop = try dwarf.getModInfo(unit).files.getOrPut(dwarf.gpa, inst_info.file);4046 const file_gop = try dwarf.getModInfo(unit).files.getOrPut(dwarf.gpa, inst_info.file);
4049 if (inst_info.inst == .main_struct_inst) {4047 if (inst_info.inst == .main_struct_inst) {
4050 const type_gop = try dwarf.types.getOrPut(dwarf.gpa, type_index);4048 const type_gop = try dwarf.types.getOrPut(dwarf.gpa, type_index);
...@@ -4348,7 +4346,7 @@ pub fn updateLineNumber(dwarf: *Dwarf, zcu: *Zcu, zir_index: InternPool.TrackedI...@@ -4348,7 +4346,7 @@ pub fn updateLineNumber(dwarf: *Dwarf, zcu: *Zcu, zir_index: InternPool.TrackedI
4348 var line_buf: [4]u8 = undefined;4346 var line_buf: [4]u8 = undefined;
4349 std.mem.writeInt(u32, &line_buf, decl.src_line + 1, dwarf.endian);4347 std.mem.writeInt(u32, &line_buf, decl.src_line + 1, dwarf.endian);
43504348
4351 const unit = dwarf.debug_info.section.getUnit(dwarf.getUnitIfExists(file.mod) orelse return);4349 const unit = dwarf.debug_info.section.getUnit(dwarf.getUnitIfExists(file.mod.?) orelse return);
4352 const entry = unit.getEntry(dwarf.decls.get(zir_index) orelse return);4350 const entry = unit.getEntry(dwarf.decls.get(zir_index) orelse return);
4353 try dwarf.getFile().?.pwriteAll(&line_buf, dwarf.debug_info.section.off(dwarf) + unit.off + unit.header_len + entry.off + DebugInfo.declEntryLineOff(dwarf));4351 try dwarf.getFile().?.pwriteAll(&line_buf, dwarf.debug_info.section.off(dwarf) + unit.off + unit.header_len + entry.off + DebugInfo.declEntryLineOff(dwarf));
4354}4352}
...@@ -4418,18 +4416,10 @@ pub fn flushModule(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void {...@@ -4418,18 +4416,10 @@ pub fn flushModule(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void {
4418 try wip_nav.updateLazy(.unneeded);4416 try wip_nav.updateLazy(.unneeded);
4419 }4417 }
44204418
4421 {4419 for (dwarf.mods.keys(), dwarf.mods.values()) |mod, *mod_info| {
4422 const cwd = try std.process.getCwdAlloc(dwarf.gpa);4420 const root_dir_path = try mod.root.toAbsolute(zcu.comp.dirs, dwarf.gpa);
4423 defer dwarf.gpa.free(cwd);4421 defer dwarf.gpa.free(root_dir_path);
4424 for (dwarf.mods.keys(), dwarf.mods.values()) |mod, *mod_info| {4422 mod_info.root_dir_path = try dwarf.debug_line_str.addString(dwarf, root_dir_path);
4425 const root_dir_path = try std.fs.path.resolve(dwarf.gpa, &.{
4426 cwd,
4427 mod.root.root_dir.path orelse "",
4428 mod.root.sub_path,
4429 });
4430 defer dwarf.gpa.free(root_dir_path);
4431 mod_info.root_dir_path = try dwarf.debug_line_str.addString(dwarf, root_dir_path);
4432 }
4433 }4423 }
44344424
4435 var header = std.ArrayList(u8).init(dwarf.gpa);4425 var header = std.ArrayList(u8).init(dwarf.gpa);
...@@ -4687,7 +4677,7 @@ pub fn flushModule(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void {...@@ -4687,7 +4677,7 @@ pub fn flushModule(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void {
4687 header.appendNTimesAssumeCapacity(0, dwarf.sectionOffsetBytes());4677 header.appendNTimesAssumeCapacity(0, dwarf.sectionOffsetBytes());
4688 dwarf.writeInt(4678 dwarf.writeInt(
4689 header.addManyAsSliceAssumeCapacity(dir_index_info.bytes),4679 header.addManyAsSliceAssumeCapacity(dir_index_info.bytes),
4690 mod_info.dirs.getIndex(dwarf.getUnitIfExists(file.mod).?).?,4680 mod_info.dirs.getIndex(dwarf.getUnitIfExists(file.mod.?).?) orelse 0,
4691 );4681 );
4692 unit.cross_section_relocs.appendAssumeCapacity(.{4682 unit.cross_section_relocs.appendAssumeCapacity(.{
4693 .source_off = @intCast(header.items.len),4683 .source_off = @intCast(header.items.len),
...@@ -4695,7 +4685,7 @@ pub fn flushModule(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void {...@@ -4695,7 +4685,7 @@ pub fn flushModule(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void {
4695 .target_unit = StringSection.unit,4685 .target_unit = StringSection.unit,
4696 .target_entry = (try dwarf.debug_line_str.addString(4686 .target_entry = (try dwarf.debug_line_str.addString(
4697 dwarf,4687 dwarf,
4698 if (file.mod.builtin_file == file) file.source.? else "",4688 if (file.is_builtin) file.source.? else "",
4699 )).toOptional(),4689 )).toOptional(),
4700 });4690 });
4701 header.appendNTimesAssumeCapacity(0, dwarf.sectionOffsetBytes());4691 header.appendNTimesAssumeCapacity(0, dwarf.sectionOffsetBytes());
src/link/Elf/ZigObject.zig+2-2
...@@ -1201,7 +1201,7 @@ fn getNavShdrIndex(...@@ -1201,7 +1201,7 @@ fn getNavShdrIndex(
1201 return osec;1201 return osec;
1202 }1202 }
1203 if (nav_init != .none and Value.fromInterned(nav_init).isUndefDeep(zcu))1203 if (nav_init != .none and Value.fromInterned(nav_init).isUndefDeep(zcu))
1204 return switch (zcu.navFileScope(nav_index).mod.optimize_mode) {1204 return switch (zcu.navFileScope(nav_index).mod.?.optimize_mode) {
1205 .Debug, .ReleaseSafe => {1205 .Debug, .ReleaseSafe => {
1206 if (self.data_index) |symbol_index|1206 if (self.data_index) |symbol_index|
1207 return self.symbol(symbol_index).outputShndx(elf_file).?;1207 return self.symbol(symbol_index).outputShndx(elf_file).?;
...@@ -1271,7 +1271,7 @@ fn updateNavCode(...@@ -1271,7 +1271,7 @@ fn updateNavCode(
12711271
1272 log.debug("updateNavCode {}({d})", .{ nav.fqn.fmt(ip), nav_index });1272 log.debug("updateNavCode {}({d})", .{ nav.fqn.fmt(ip), nav_index });
12731273
1274 const target = zcu.navFileScope(nav_index).mod.resolved_target.result;1274 const target = zcu.navFileScope(nav_index).mod.?.resolved_target.result;
1275 const required_alignment = switch (pt.navAlignment(nav_index)) {1275 const required_alignment = switch (pt.navAlignment(nav_index)) {
1276 .none => target_util.defaultFunctionAlignment(target),1276 .none => target_util.defaultFunctionAlignment(target),
1277 else => |a| a.maxStrict(target_util.minFunctionAlignment(target)),1277 else => |a| a.maxStrict(target_util.minFunctionAlignment(target)),
src/link/MachO.zig+3-3
...@@ -867,11 +867,11 @@ pub fn resolveLibSystem(...@@ -867,11 +867,11 @@ pub fn resolveLibSystem(
867 success: {867 success: {
868 if (self.sdk_layout) |sdk_layout| switch (sdk_layout) {868 if (self.sdk_layout) |sdk_layout| switch (sdk_layout) {
869 .sdk => {869 .sdk => {
870 const dir = try fs.path.join(arena, &[_][]const u8{ comp.sysroot.?, "usr", "lib" });870 const dir = try fs.path.join(arena, &.{ comp.sysroot.?, "usr", "lib" });
871 if (try accessLibPath(arena, &test_path, &checked_paths, dir, "System")) break :success;871 if (try accessLibPath(arena, &test_path, &checked_paths, dir, "System")) break :success;
872 },872 },
873 .vendored => {873 .vendored => {
874 const dir = try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libc", "darwin" });874 const dir = try comp.dirs.zig_lib.join(arena, &.{ "libc", "darwin" });
875 if (try accessLibPath(arena, &test_path, &checked_paths, dir, "System")) break :success;875 if (try accessLibPath(arena, &test_path, &checked_paths, dir, "System")) break :success;
876 },876 },
877 };877 };
...@@ -4406,7 +4406,7 @@ fn inferSdkVersion(comp: *Compilation, sdk_layout: SdkLayout) ?std.SemanticVersi...@@ -4406,7 +4406,7 @@ fn inferSdkVersion(comp: *Compilation, sdk_layout: SdkLayout) ?std.SemanticVersi
44064406
4407 const sdk_dir = switch (sdk_layout) {4407 const sdk_dir = switch (sdk_layout) {
4408 .sdk => comp.sysroot.?,4408 .sdk => comp.sysroot.?,
4409 .vendored => fs.path.join(arena, &.{ comp.zig_lib_directory.path.?, "libc", "darwin" }) catch return null,4409 .vendored => fs.path.join(arena, &.{ comp.dirs.zig_lib.path.?, "libc", "darwin" }) catch return null,
4410 };4410 };
4411 if (readSdkVersionFromSettings(arena, sdk_dir)) |ver| {4411 if (readSdkVersionFromSettings(arena, sdk_dir)) |ver| {
4412 return parseSdkVersion(ver);4412 return parseSdkVersion(ver);
src/link/MachO/ZigObject.zig+2-2
...@@ -954,7 +954,7 @@ fn updateNavCode(...@@ -954,7 +954,7 @@ fn updateNavCode(
954954
955 log.debug("updateNavCode {} 0x{x}", .{ nav.fqn.fmt(ip), nav_index });955 log.debug("updateNavCode {} 0x{x}", .{ nav.fqn.fmt(ip), nav_index });
956956
957 const target = zcu.navFileScope(nav_index).mod.resolved_target.result;957 const target = zcu.navFileScope(nav_index).mod.?.resolved_target.result;
958 const required_alignment = switch (pt.navAlignment(nav_index)) {958 const required_alignment = switch (pt.navAlignment(nav_index)) {
959 .none => target_util.defaultFunctionAlignment(target),959 .none => target_util.defaultFunctionAlignment(target),
960 else => |a| a.maxStrict(target_util.minFunctionAlignment(target)),960 else => |a| a.maxStrict(target_util.minFunctionAlignment(target)),
...@@ -1184,7 +1184,7 @@ fn getNavOutputSection(...@@ -1184,7 +1184,7 @@ fn getNavOutputSection(
1184 }1184 }
1185 if (is_const) return macho_file.zig_const_sect_index.?;1185 if (is_const) return macho_file.zig_const_sect_index.?;
1186 if (nav_init != .none and Value.fromInterned(nav_init).isUndefDeep(zcu))1186 if (nav_init != .none and Value.fromInterned(nav_init).isUndefDeep(zcu))
1187 return switch (zcu.navFileScope(nav_index).mod.optimize_mode) {1187 return switch (zcu.navFileScope(nav_index).mod.?.optimize_mode) {
1188 .Debug, .ReleaseSafe => macho_file.zig_data_sect_index.?,1188 .Debug, .ReleaseSafe => macho_file.zig_data_sect_index.?,
1189 .ReleaseFast, .ReleaseSmall => macho_file.zig_bss_sect_index.?,1189 .ReleaseFast, .ReleaseSmall => macho_file.zig_bss_sect_index.?,
1190 };1190 };
src/link/Plan9.zig+9-13
...@@ -315,8 +315,9 @@ pub fn createEmpty(...@@ -315,8 +315,9 @@ pub fn createEmpty(
315}315}
316316
317fn putFn(self: *Plan9, nav_index: InternPool.Nav.Index, out: FnNavOutput) !void {317fn putFn(self: *Plan9, nav_index: InternPool.Nav.Index, out: FnNavOutput) !void {
318 const gpa = self.base.comp.gpa;318 const comp = self.base.comp;
319 const zcu = self.base.comp.zcu.?;319 const gpa = comp.gpa;
320 const zcu = comp.zcu.?;
320 const file_scope = zcu.navFileScopeIndex(nav_index);321 const file_scope = zcu.navFileScopeIndex(nav_index);
321 const fn_map_res = try self.fn_nav_table.getOrPut(gpa, file_scope);322 const fn_map_res = try self.fn_nav_table.getOrPut(gpa, file_scope);
322 if (fn_map_res.found_existing) {323 if (fn_map_res.found_existing) {
...@@ -345,14 +346,11 @@ fn putFn(self: *Plan9, nav_index: InternPool.Nav.Index, out: FnNavOutput) !void...@@ -345,14 +346,11 @@ fn putFn(self: *Plan9, nav_index: InternPool.Nav.Index, out: FnNavOutput) !void
345 try a.writer().writeInt(u16, 1, .big);346 try a.writer().writeInt(u16, 1, .big);
346347
347 // getting the full file path348 // getting the full file path
348 // TODO don't call getcwd here, that is inappropriate349 {
349 var buf: [std.fs.max_path_bytes]u8 = undefined;350 const full_path = try file.path.toAbsolute(comp.dirs, gpa);
350 const full_path = try std.fs.path.join(arena, &.{351 defer gpa.free(full_path);
351 file.mod.root.root_dir.path orelse try std.posix.getcwd(&buf),352 try self.addPathComponents(full_path, &a);
352 file.mod.root.sub_path,353 }
353 file.sub_file_path,
354 });
355 try self.addPathComponents(full_path, &a);
356354
357 // null terminate355 // null terminate
358 try a.append(0);356 try a.append(0);
...@@ -437,9 +435,7 @@ pub fn updateFunc(...@@ -437,9 +435,7 @@ pub fn updateFunc(
437 .start_line = dbg_info_output.start_line.?,435 .start_line = dbg_info_output.start_line.?,
438 .end_line = dbg_info_output.end_line,436 .end_line = dbg_info_output.end_line,
439 };437 };
440 // The awkward error handling here is due to putFn calling `std.posix.getcwd` which it should not do.438 try self.putFn(func.owner_nav, out);
441 self.putFn(func.owner_nav, out) catch |err|
442 return zcu.codegenFail(func.owner_nav, "failed to put fn: {s}", .{@errorName(err)});
443 return self.updateFinish(pt, func.owner_nav);439 return self.updateFinish(pt, func.owner_nav);
444}440}
445441
src/main.zig+228-549
...@@ -63,19 +63,7 @@ pub fn wasi_cwd() std.os.wasi.fd_t {...@@ -63,19 +63,7 @@ pub fn wasi_cwd() std.os.wasi.fd_t {
63 return cwd_fd;63 return cwd_fd;
64}64}
6565
66fn getWasiPreopen(name: []const u8) Directory {66const fatal = std.process.fatal;
67 return .{
68 .path = name,
69 .handle = .{
70 .fd = wasi_preopens.find(name) orelse fatal("WASI preopen not found: '{s}'", .{name}),
71 },
72 };
73}
74
75pub fn fatal(comptime format: []const u8, args: anytype) noreturn {
76 std.log.err(format, args);
77 process.exit(1);
78}
7967
80/// Shaming all the locations that inappropriately use an O(N) search algorithm.68/// Shaming all the locations that inappropriately use an O(N) search algorithm.
81/// Please delete this and fix the compilation errors!69/// Please delete this and fix the compilation errors!
...@@ -136,7 +124,6 @@ const debug_usage = normal_usage ++...@@ -136,7 +124,6 @@ const debug_usage = normal_usage ++
136;124;
137125
138const usage = if (build_options.enable_debug_extensions) debug_usage else normal_usage;126const usage = if (build_options.enable_debug_extensions) debug_usage else normal_usage;
139const default_local_zig_cache_basename = ".zig-cache";
140127
141var log_scopes: std.ArrayListUnmanaged([]const u8) = .empty;128var log_scopes: std.ArrayListUnmanaged([]const u8) = .empty;
142129
...@@ -377,13 +364,13 @@ fn mainArgs(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {...@@ -377,13 +364,13 @@ fn mainArgs(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
377 dev.check(.help_command);364 dev.check(.help_command);
378 return io.getStdOut().writeAll(usage);365 return io.getStdOut().writeAll(usage);
379 } else if (mem.eql(u8, cmd, "ast-check")) {366 } else if (mem.eql(u8, cmd, "ast-check")) {
380 return cmdAstCheck(gpa, arena, cmd_args);367 return cmdAstCheck(arena, cmd_args);
381 } else if (mem.eql(u8, cmd, "detect-cpu")) {368 } else if (mem.eql(u8, cmd, "detect-cpu")) {
382 return cmdDetectCpu(gpa, arena, cmd_args);369 return cmdDetectCpu(cmd_args);
383 } else if (build_options.enable_debug_extensions and mem.eql(u8, cmd, "changelist")) {370 } else if (build_options.enable_debug_extensions and mem.eql(u8, cmd, "changelist")) {
384 return cmdChangelist(gpa, arena, cmd_args);371 return cmdChangelist(arena, cmd_args);
385 } else if (build_options.enable_debug_extensions and mem.eql(u8, cmd, "dump-zir")) {372 } else if (build_options.enable_debug_extensions and mem.eql(u8, cmd, "dump-zir")) {
386 return cmdDumpZir(gpa, arena, cmd_args);373 return cmdDumpZir(arena, cmd_args);
387 } else if (build_options.enable_debug_extensions and mem.eql(u8, cmd, "llvm-ints")) {374 } else if (build_options.enable_debug_extensions and mem.eql(u8, cmd, "llvm-ints")) {
388 return cmdDumpLlvmInts(gpa, arena, cmd_args);375 return cmdDumpLlvmInts(gpa, arena, cmd_args);
389 } else {376 } else {
...@@ -809,7 +796,8 @@ const Framework = struct {...@@ -809,7 +796,8 @@ const Framework = struct {
809};796};
810797
811const CliModule = struct {798const CliModule = struct {
812 paths: Package.Module.CreateOptions.Paths,799 root_path: []const u8,
800 root_src_path: []const u8,
813 cc_argv: []const []const u8,801 cc_argv: []const []const u8,
814 inherited: Package.Module.CreateOptions.Inherited,802 inherited: Package.Module.CreateOptions.Inherited,
815 target_arch_os_abi: ?[]const u8,803 target_arch_os_abi: ?[]const u8,
...@@ -976,7 +964,7 @@ fn buildOutputType(...@@ -976,7 +964,7 @@ fn buildOutputType(
976 // error output consistent. "root" is special.964 // error output consistent. "root" is special.
977 var create_module: CreateModule = .{965 var create_module: CreateModule = .{
978 // Populated just before the call to `createModule`.966 // Populated just before the call to `createModule`.
979 .global_cache_directory = undefined,967 .dirs = undefined,
980 .object_format = null,968 .object_format = null,
981 .dynamic_linker = null,969 .dynamic_linker = null,
982 .modules = .{},970 .modules = .{},
...@@ -1859,7 +1847,7 @@ fn buildOutputType(...@@ -1859,7 +1847,7 @@ fn buildOutputType(
1859 } else root_src_file = arg;1847 } else root_src_file = arg;
1860 },1848 },
1861 .def, .unknown => {1849 .def, .unknown => {
1862 if (std.ascii.eqlIgnoreCase(".xml", std.fs.path.extension(arg))) {1850 if (std.ascii.eqlIgnoreCase(".xml", fs.path.extension(arg))) {
1863 warn("embedded manifest files must have the extension '.manifest'", .{});1851 warn("embedded manifest files must have the extension '.manifest'", .{});
1864 }1852 }
1865 fatal("unrecognized file extension of parameter '{s}'", .{arg});1853 fatal("unrecognized file extension of parameter '{s}'", .{arg});
...@@ -2924,13 +2912,14 @@ fn buildOutputType(...@@ -2924,13 +2912,14 @@ fn buildOutputType(
2924 }2912 }
29252913
2926 implicit_root_mod: {2914 implicit_root_mod: {
2927 const unresolved_src_path = b: {2915 const src_path = b: {
2928 if (root_src_file) |src_path| {2916 if (root_src_file) |src_path| {
2929 if (create_module.modules.count() != 0) {2917 if (create_module.modules.count() != 0) {
2930 fatal("main module provided both by '-M{s}={}{s}' and by positional argument '{s}'", .{2918 fatal("main module provided both by '-M{s}={s}{c}{s}' and by positional argument '{s}'", .{
2931 create_module.modules.keys()[0],2919 create_module.modules.keys()[0],
2932 create_module.modules.values()[0].paths.root,2920 create_module.modules.values()[0].root_path,
2933 create_module.modules.values()[0].paths.root_src_path,2921 fs.path.sep,
2922 create_module.modules.values()[0].root_src_path,
2934 src_path,2923 src_path,
2935 });2924 });
2936 }2925 }
...@@ -2987,20 +2976,14 @@ fn buildOutputType(...@@ -2987,20 +2976,14 @@ fn buildOutputType(
2987 if (mod_opts.error_tracing == true)2976 if (mod_opts.error_tracing == true)
2988 create_module.opts.any_error_tracing = true;2977 create_module.opts.any_error_tracing = true;
29892978
2990 const src_path = try introspect.resolvePath(arena, unresolved_src_path);
2991 const name = switch (arg_mode) {2979 const name = switch (arg_mode) {
2992 .zig_test => "test",2980 .zig_test => "test",
2993 .build, .cc, .cpp, .translate_c, .zig_test_obj, .run => fs.path.stem(fs.path.basename(src_path)),2981 .build, .cc, .cpp, .translate_c, .zig_test_obj, .run => fs.path.stem(fs.path.basename(src_path)),
2994 };2982 };
29952983
2996 try create_module.modules.put(arena, name, .{2984 try create_module.modules.put(arena, name, .{
2997 .paths = .{2985 .root_path = fs.path.dirname(src_path) orelse ".",
2998 .root = .{2986 .root_src_path = fs.path.basename(src_path),
2999 .root_dir = Cache.Directory.cwd(),
3000 .sub_path = fs.path.dirname(src_path) orelse "",
3001 },
3002 .root_src_path = fs.path.basename(src_path),
3003 },
3004 .cc_argv = try cc_argv.toOwnedSlice(arena),2987 .cc_argv = try cc_argv.toOwnedSlice(arena),
3005 .inherited = mod_opts,2988 .inherited = mod_opts,
3006 .target_arch_os_abi = target_arch_os_abi,2989 .target_arch_os_abi = target_arch_os_abi,
...@@ -3036,85 +3019,50 @@ fn buildOutputType(...@@ -3036,85 +3019,50 @@ fn buildOutputType(
3036 });3019 });
3037 }3020 }
30383021
3039 const self_exe_path: ?[]const u8 = if (!process.can_spawn)3022 const self_exe_path = switch (native_os) {
3040 null3023 .wasi => {},
3041 else3024 else => fs.selfExePathAlloc(arena) catch |err| {
3042 introspect.findZigExePath(arena) catch |err| {
3043 fatal("unable to find zig self exe path: {s}", .{@errorName(err)});3025 fatal("unable to find zig self exe path: {s}", .{@errorName(err)});
3044 };3026 },
3045
3046 var zig_lib_directory: Directory = d: {
3047 if (override_lib_dir) |unresolved_lib_dir| {
3048 const lib_dir = try introspect.resolvePath(arena, unresolved_lib_dir);
3049 break :d .{
3050 .path = lib_dir,
3051 .handle = fs.cwd().openDir(lib_dir, .{}) catch |err| {
3052 fatal("unable to open zig lib directory '{s}': {s}", .{ lib_dir, @errorName(err) });
3053 },
3054 };
3055 } else if (native_os == .wasi) {
3056 break :d getWasiPreopen("/lib");
3057 } else if (self_exe_path) |p| {
3058 break :d introspect.findZigLibDirFromSelfExe(arena, p) catch |err| {
3059 fatal("unable to find zig installation directory '{s}': {s}", .{ p, @errorName(err) });
3060 };
3061 } else {
3062 unreachable;
3063 }
3064 };3027 };
3065 defer zig_lib_directory.handle.close();
30663028
3067 var global_cache_directory: Directory = l: {3029 // This `init` calls `fatal` on error.
3068 if (override_global_cache_dir) |p| {3030 var dirs: Compilation.Directories = .init(
3069 break :l .{3031 arena,
3070 .handle = try fs.cwd().makeOpenPath(p, .{}),3032 override_lib_dir,
3071 .path = p,3033 override_global_cache_dir,
3034 s: {
3035 if (override_local_cache_dir) |p| break :s .{ .override = p };
3036 break :s switch (arg_mode) {
3037 .run => .global,
3038 else => .search,
3072 };3039 };
3073 }3040 },
3074 if (native_os == .wasi) {3041 if (native_os == .wasi) wasi_preopens,
3075 break :l getWasiPreopen("/cache");3042 self_exe_path,
3076 }3043 );
3077 const p = try introspect.resolveGlobalCacheDir(arena);3044 defer dirs.deinit();
3078 break :l .{
3079 .handle = try fs.cwd().makeOpenPath(p, .{}),
3080 .path = p,
3081 };
3082 };
3083 defer global_cache_directory.handle.close();
30843045
3085 if (linker_optimization) |o| {3046 if (linker_optimization) |o| {
3086 warn("ignoring deprecated linker optimization setting '{s}'", .{o});3047 warn("ignoring deprecated linker optimization setting '{s}'", .{o});
3087 }3048 }
30883049
3089 create_module.global_cache_directory = global_cache_directory;3050 create_module.dirs = dirs;
3090 create_module.opts.emit_llvm_ir = emit_llvm_ir != .no;3051 create_module.opts.emit_llvm_ir = emit_llvm_ir != .no;
3091 create_module.opts.emit_llvm_bc = emit_llvm_bc != .no;3052 create_module.opts.emit_llvm_bc = emit_llvm_bc != .no;
3092 create_module.opts.emit_bin = emit_bin != .no;3053 create_module.opts.emit_bin = emit_bin != .no;
3093 create_module.opts.any_c_source_files = create_module.c_source_files.items.len != 0;3054 create_module.opts.any_c_source_files = create_module.c_source_files.items.len != 0;
30943055
3095 var builtin_modules: std.StringHashMapUnmanaged(*Package.Module) = .empty;3056 const main_mod = try createModule(gpa, arena, &create_module, 0, null, color);
3096 // `builtin_modules` allocated into `arena`, so no deinit
3097 const main_mod = try createModule(gpa, arena, &create_module, 0, null, zig_lib_directory, &builtin_modules, color);
3098 for (create_module.modules.keys(), create_module.modules.values()) |key, cli_mod| {3057 for (create_module.modules.keys(), create_module.modules.values()) |key, cli_mod| {
3099 if (cli_mod.resolved == null)3058 if (cli_mod.resolved == null)
3100 fatal("module '{s}' declared but not used", .{key});3059 fatal("module '{s}' declared but not used", .{key});
3101 }3060 }
31023061
3103 // When you're testing std, the main module is std. In that case,3062 // When you're testing std, the main module is std, and we need to avoid duplicating the module.
3104 // we'll just set the std module to the main one, since avoiding3063 const main_mod_is_std = main_mod.root.root == .zig_lib and
3105 // the errors caused by duplicating it is more effort than it's3064 mem.eql(u8, main_mod.root.sub_path, "std") and
3106 // worth.3065 mem.eql(u8, main_mod.root_src_path, "std.zig");
3107 const main_mod_is_std = m: {
3108 const std_path = try fs.path.resolve(arena, &.{
3109 zig_lib_directory.path orelse ".", "std", "std.zig",
3110 });
3111 const main_path = try fs.path.resolve(arena, &.{
3112 main_mod.root.root_dir.path orelse ".",
3113 main_mod.root.sub_path,
3114 main_mod.root_src_path,
3115 });
3116 break :m mem.eql(u8, main_path, std_path);
3117 };
31183066
3119 const std_mod = m: {3067 const std_mod = m: {
3120 if (main_mod_is_std) break :m main_mod;3068 if (main_mod_is_std) break :m main_mod;
...@@ -3126,12 +3074,8 @@ fn buildOutputType(...@@ -3126,12 +3074,8 @@ fn buildOutputType(
3126 .zig_test, .zig_test_obj => root_mod: {3074 .zig_test, .zig_test_obj => root_mod: {
3127 const test_mod = if (test_runner_path) |test_runner| test_mod: {3075 const test_mod = if (test_runner_path) |test_runner| test_mod: {
3128 const test_mod = try Package.Module.create(arena, .{3076 const test_mod = try Package.Module.create(arena, .{
3129 .global_cache_directory = global_cache_directory,
3130 .paths = .{3077 .paths = .{
3131 .root = .{3078 .root = try .fromUnresolved(arena, dirs, &.{fs.path.dirname(test_runner) orelse "."}),
3132 .root_dir = Cache.Directory.cwd(),
3133 .sub_path = fs.path.dirname(test_runner) orelse "",
3134 },
3135 .root_src_path = fs.path.basename(test_runner),3079 .root_src_path = fs.path.basename(test_runner),
3136 },3080 },
3137 .fully_qualified_name = "root",3081 .fully_qualified_name = "root",
...@@ -3139,18 +3083,12 @@ fn buildOutputType(...@@ -3139,18 +3083,12 @@ fn buildOutputType(
3139 .inherited = .{},3083 .inherited = .{},
3140 .global = create_module.resolved_options,3084 .global = create_module.resolved_options,
3141 .parent = main_mod,3085 .parent = main_mod,
3142 .builtin_mod = main_mod.getBuiltinDependency(),
3143 .builtin_modules = null, // `builtin_mod` is specified
3144 });3086 });
3145 test_mod.deps = try main_mod.deps.clone(arena);3087 test_mod.deps = try main_mod.deps.clone(arena);
3146 break :test_mod test_mod;3088 break :test_mod test_mod;
3147 } else try Package.Module.create(arena, .{3089 } else try Package.Module.create(arena, .{
3148 .global_cache_directory = global_cache_directory,
3149 .paths = .{3090 .paths = .{
3150 .root = .{3091 .root = try .fromRoot(arena, dirs, .zig_lib, "compiler"),
3151 .root_dir = zig_lib_directory,
3152 .sub_path = "compiler",
3153 },
3154 .root_src_path = "test_runner.zig",3092 .root_src_path = "test_runner.zig",
3155 },3093 },
3156 .fully_qualified_name = "root",3094 .fully_qualified_name = "root",
...@@ -3158,8 +3096,6 @@ fn buildOutputType(...@@ -3158,8 +3096,6 @@ fn buildOutputType(
3158 .inherited = .{},3096 .inherited = .{},
3159 .global = create_module.resolved_options,3097 .global = create_module.resolved_options,
3160 .parent = main_mod,3098 .parent = main_mod,
3161 .builtin_mod = main_mod.getBuiltinDependency(),
3162 .builtin_modules = null, // `builtin_mod` is specified
3163 });3099 });
31643100
3165 break :root_mod test_mod;3101 break :root_mod test_mod;
...@@ -3469,50 +3405,6 @@ fn buildOutputType(...@@ -3469,50 +3405,6 @@ fn buildOutputType(
3469 });3405 });
3470 defer thread_pool.deinit();3406 defer thread_pool.deinit();
34713407
3472 var cleanup_local_cache_dir: ?fs.Dir = null;
3473 defer if (cleanup_local_cache_dir) |*dir| dir.close();
3474
3475 var local_cache_directory: Directory = l: {
3476 if (override_local_cache_dir) |local_cache_dir_path| {
3477 const dir = try fs.cwd().makeOpenPath(local_cache_dir_path, .{});
3478 cleanup_local_cache_dir = dir;
3479 break :l .{
3480 .handle = dir,
3481 .path = local_cache_dir_path,
3482 };
3483 }
3484 if (arg_mode == .run) {
3485 break :l global_cache_directory;
3486 }
3487
3488 // search upwards from cwd until we find directory with build.zig
3489 const cwd_path = try process.getCwdAlloc(arena);
3490 var dirname: []const u8 = cwd_path;
3491 while (true) {
3492 const joined_path = try fs.path.join(arena, &.{
3493 dirname, Package.build_zig_basename,
3494 });
3495 if (fs.cwd().access(joined_path, .{})) |_| {
3496 const cache_dir_path = try fs.path.join(arena, &.{ dirname, default_local_zig_cache_basename });
3497 const dir = try fs.cwd().makeOpenPath(cache_dir_path, .{});
3498 cleanup_local_cache_dir = dir;
3499 break :l .{ .handle = dir, .path = cache_dir_path };
3500 } else |err| switch (err) {
3501 error.FileNotFound => {
3502 dirname = fs.path.dirname(dirname) orelse {
3503 break :l global_cache_directory;
3504 };
3505 continue;
3506 },
3507 else => break :l global_cache_directory,
3508 }
3509 }
3510
3511 // Otherwise we really don't have a reasonable place to put the local cache directory,
3512 // so we utilize the global one.
3513 break :l global_cache_directory;
3514 };
3515
3516 for (create_module.c_source_files.items) |*src| {3408 for (create_module.c_source_files.items) |*src| {
3517 if (!mem.eql(u8, src.src_path, "-")) continue;3409 if (!mem.eql(u8, src.src_path, "-")) continue;
35183410
...@@ -3524,14 +3416,14 @@ fn buildOutputType(...@@ -3524,14 +3416,14 @@ fn buildOutputType(
3524 const dump_path = try std.fmt.allocPrint(arena, "tmp" ++ sep ++ "{x}-dump-stdin{s}", .{3416 const dump_path = try std.fmt.allocPrint(arena, "tmp" ++ sep ++ "{x}-dump-stdin{s}", .{
3525 std.crypto.random.int(u64), ext.canonicalName(target),3417 std.crypto.random.int(u64), ext.canonicalName(target),
3526 });3418 });
3527 try local_cache_directory.handle.makePath("tmp");3419 try dirs.local_cache.handle.makePath("tmp");
35283420
3529 // Note that in one of the happy paths, execve() is used to switch to3421 // Note that in one of the happy paths, execve() is used to switch to
3530 // clang in which case any cleanup logic that exists for this temporary3422 // clang in which case any cleanup logic that exists for this temporary
3531 // file will not run and this temp file will be leaked. The filename3423 // file will not run and this temp file will be leaked. The filename
3532 // will be a hash of its contents — so multiple invocations of3424 // will be a hash of its contents — so multiple invocations of
3533 // `zig cc -` will result in the same temp file name.3425 // `zig cc -` will result in the same temp file name.
3534 var f = try local_cache_directory.handle.createFile(dump_path, .{});3426 var f = try dirs.local_cache.handle.createFile(dump_path, .{});
3535 defer f.close();3427 defer f.close();
35363428
3537 // Re-using the hasher from Cache, since the functional requirements3429 // Re-using the hasher from Cache, since the functional requirements
...@@ -3550,10 +3442,10 @@ fn buildOutputType(...@@ -3550,10 +3442,10 @@ fn buildOutputType(
3550 std.fmt.fmtSliceHexLower(&bin_digest),3442 std.fmt.fmtSliceHexLower(&bin_digest),
3551 ext.canonicalName(target),3443 ext.canonicalName(target),
3552 });3444 });
3553 try local_cache_directory.handle.rename(dump_path, sub_path);3445 try dirs.local_cache.handle.rename(dump_path, sub_path);
35543446
3555 // Convert `sub_path` to be relative to current working directory.3447 // Convert `sub_path` to be relative to current working directory.
3556 src.src_path = try local_cache_directory.join(arena, &.{sub_path});3448 src.src_path = try dirs.local_cache.join(arena, &.{sub_path});
3557 }3449 }
35583450
3559 if (build_options.have_llvm and emit_asm != .no) {3451 if (build_options.have_llvm and emit_asm != .no) {
...@@ -3595,11 +3487,12 @@ fn buildOutputType(...@@ -3595,11 +3487,12 @@ fn buildOutputType(
3595 defer file_system_inputs.deinit(gpa);3487 defer file_system_inputs.deinit(gpa);
35963488
3597 const comp = Compilation.create(gpa, arena, .{3489 const comp = Compilation.create(gpa, arena, .{
3598 .zig_lib_directory = zig_lib_directory,3490 .dirs = dirs,
3599 .local_cache_directory = local_cache_directory,
3600 .global_cache_directory = global_cache_directory,
3601 .thread_pool = &thread_pool,3491 .thread_pool = &thread_pool,
3602 .self_exe_path = self_exe_path,3492 .self_exe_path = switch (native_os) {
3493 .wasi => null,
3494 else => self_exe_path,
3495 },
3603 .config = create_module.resolved_options,3496 .config = create_module.resolved_options,
3604 .root_name = root_name,3497 .root_name = root_name,
3605 .sysroot = create_module.sysroot,3498 .sysroot = create_module.sysroot,
...@@ -3757,14 +3650,17 @@ fn buildOutputType(...@@ -3757,14 +3650,17 @@ fn buildOutputType(
3757 error.ExportTableAndImportTableConflict => {3650 error.ExportTableAndImportTableConflict => {
3758 fatal("--import-table and --export-table may not be used together", .{});3651 fatal("--import-table and --export-table may not be used together", .{});
3759 },3652 },
3653 error.IllegalZigImport => {
3654 fatal("this compiler implementation does not support importing the root source file of a provided module", .{});
3655 },
3760 else => fatal("unable to create compilation: {s}", .{@errorName(err)}),3656 else => fatal("unable to create compilation: {s}", .{@errorName(err)}),
3761 };3657 };
3762 var comp_destroyed = false;3658 var comp_destroyed = false;
3763 defer if (!comp_destroyed) comp.destroy();3659 defer if (!comp_destroyed) comp.destroy();
37643660
3765 if (show_builtin) {3661 if (show_builtin) {
3766 const builtin_mod = comp.root_mod.getBuiltinDependency();3662 const builtin_opts = comp.root_mod.getBuiltinOptions(comp.config);
3767 const source = builtin_mod.builtin_file.?.source.?;3663 const source = try builtin_opts.generate(arena);
3768 return std.io.getStdOut().writeAll(source);3664 return std.io.getStdOut().writeAll(source);
3769 }3665 }
3770 switch (listen) {3666 switch (listen) {
...@@ -3844,7 +3740,7 @@ fn buildOutputType(...@@ -3844,7 +3740,7 @@ fn buildOutputType(
3844 c_code_directory.path orelse ".", c_code_loc.basename,3740 c_code_directory.path orelse ".", c_code_loc.basename,
3845 });3741 });
3846 try test_exec_args.appendSlice(arena, &.{ self_exe_path, "run" });3742 try test_exec_args.appendSlice(arena, &.{ self_exe_path, "run" });
3847 if (zig_lib_directory.path) |p| {3743 if (dirs.zig_lib.path) |p| {
3848 try test_exec_args.appendSlice(arena, &.{ "-I", p });3744 try test_exec_args.appendSlice(arena, &.{ "-I", p });
3849 }3745 }
38503746
...@@ -3875,7 +3771,7 @@ fn buildOutputType(...@@ -3875,7 +3771,7 @@ fn buildOutputType(
3875 gpa,3771 gpa,
3876 arena,3772 arena,
3877 test_exec_args.items,3773 test_exec_args.items,
3878 self_exe_path.?,3774 self_exe_path,
3879 arg_mode,3775 arg_mode,
3880 &target,3776 &target,
3881 &comp_destroyed,3777 &comp_destroyed,
...@@ -3890,7 +3786,7 @@ fn buildOutputType(...@@ -3890,7 +3786,7 @@ fn buildOutputType(
3890}3786}
38913787
3892const CreateModule = struct {3788const CreateModule = struct {
3893 global_cache_directory: Cache.Directory,3789 dirs: Compilation.Directories,
3894 modules: std.StringArrayHashMapUnmanaged(CliModule),3790 modules: std.StringArrayHashMapUnmanaged(CliModule),
3895 opts: Compilation.Config.Options,3791 opts: Compilation.Config.Options,
3896 dynamic_linker: ?[]const u8,3792 dynamic_linker: ?[]const u8,
...@@ -3937,8 +3833,6 @@ fn createModule(...@@ -3937,8 +3833,6 @@ fn createModule(
3937 create_module: *CreateModule,3833 create_module: *CreateModule,
3938 index: usize,3834 index: usize,
3939 parent: ?*Package.Module,3835 parent: ?*Package.Module,
3940 zig_lib_directory: Cache.Directory,
3941 builtin_modules: *std.StringHashMapUnmanaged(*Package.Module),
3942 color: std.zig.Color,3836 color: std.zig.Color,
3943) Allocator.Error!*Package.Module {3837) Allocator.Error!*Package.Module {
3944 const cli_mod = &create_module.modules.values()[index];3838 const cli_mod = &create_module.modules.values()[index];
...@@ -4069,7 +3963,7 @@ fn createModule(...@@ -4069,7 +3963,7 @@ fn createModule(
4069 }3963 }
40703964
4071 if (target.isMinGW()) {3965 if (target.isMinGW()) {
4072 const exists = mingw.libExists(arena, target, zig_lib_directory, lib_name) catch |err| {3966 const exists = mingw.libExists(arena, target, create_module.dirs.zig_lib, lib_name) catch |err| {
4073 fatal("failed to check zig installation for DLL import libs: {s}", .{3967 fatal("failed to check zig installation for DLL import libs: {s}", .{
4074 @errorName(err),3968 @errorName(err),
4075 });3969 });
...@@ -4225,17 +4119,19 @@ fn createModule(...@@ -4225,17 +4119,19 @@ fn createModule(
4225 };4119 };
4226 }4120 }
42274121
4122 const root: Compilation.Path = try .fromUnresolved(arena, create_module.dirs, &.{cli_mod.root_path});
4123
4228 const mod = Package.Module.create(arena, .{4124 const mod = Package.Module.create(arena, .{
4229 .global_cache_directory = create_module.global_cache_directory,4125 .paths = .{
4230 .paths = cli_mod.paths,4126 .root = root,
4127 .root_src_path = cli_mod.root_src_path,
4128 },
4231 .fully_qualified_name = name,4129 .fully_qualified_name = name,
42324130
4233 .cc_argv = cli_mod.cc_argv,4131 .cc_argv = cli_mod.cc_argv,
4234 .inherited = cli_mod.inherited,4132 .inherited = cli_mod.inherited,
4235 .global = create_module.resolved_options,4133 .global = create_module.resolved_options,
4236 .parent = parent,4134 .parent = parent,
4237 .builtin_mod = null,
4238 .builtin_modules = builtin_modules,
4239 }) catch |err| switch (err) {4135 }) catch |err| switch (err) {
4240 error.ValgrindUnsupportedOnTarget => fatal("unable to create module '{s}': valgrind does not support the selected target CPU architecture", .{name}),4136 error.ValgrindUnsupportedOnTarget => fatal("unable to create module '{s}': valgrind does not support the selected target CPU architecture", .{name}),
4241 error.TargetRequiresSingleThreaded => fatal("unable to create module '{s}': the selected target does not support multithreading", .{name}),4137 error.TargetRequiresSingleThreaded => fatal("unable to create module '{s}': the selected target does not support multithreading", .{name}),
...@@ -4258,7 +4154,7 @@ fn createModule(...@@ -4258,7 +4154,7 @@ fn createModule(
4258 for (cli_mod.deps) |dep| {4154 for (cli_mod.deps) |dep| {
4259 const dep_index = create_module.modules.getIndex(dep.value) orelse4155 const dep_index = create_module.modules.getIndex(dep.value) orelse
4260 fatal("module '{s}' depends on non-existent module '{s}'", .{ name, dep.key });4156 fatal("module '{s}' depends on non-existent module '{s}'", .{ name, dep.key });
4261 const dep_mod = try createModule(gpa, arena, create_module, dep_index, mod, zig_lib_directory, builtin_modules, color);4157 const dep_mod = try createModule(gpa, arena, create_module, dep_index, mod, color);
4262 try mod.deps.put(arena, dep.key, dep_mod);4158 try mod.deps.put(arena, dep.key, dep_mod);
4263 }4159 }
42644160
...@@ -4544,15 +4440,13 @@ fn runOrTestHotSwap(...@@ -4544,15 +4440,13 @@ fn runOrTestHotSwap(
4544 // tmp zig-cache and use it to spawn the child process. This way we are free to update4440 // tmp zig-cache and use it to spawn the child process. This way we are free to update
4545 // the binary with each requested hot update.4441 // the binary with each requested hot update.
4546 .windows => blk: {4442 .windows => blk: {
4547 try lf.emit.root_dir.handle.copyFile(lf.emit.sub_path, comp.local_cache_directory.handle, lf.emit.sub_path, .{});4443 try lf.emit.root_dir.handle.copyFile(lf.emit.sub_path, comp.dirs.local_cache.handle, lf.emit.sub_path, .{});
4548 break :blk try fs.path.join(gpa, &[_][]const u8{4444 break :blk try fs.path.join(gpa, &.{ comp.dirs.local_cache.path orelse ".", lf.emit.sub_path });
4549 comp.local_cache_directory.path orelse ".", lf.emit.sub_path,
4550 });
4551 },4445 },
45524446
4553 // A naive `directory.join` here will indeed get the correct path to the binary,4447 // A naive `directory.join` here will indeed get the correct path to the binary,
4554 // however, in the case of cwd, we actually want `./foo` so that the path can be executed.4448 // however, in the case of cwd, we actually want `./foo` so that the path can be executed.
4555 else => try fs.path.join(gpa, &[_][]const u8{4449 else => try fs.path.join(gpa, &.{
4556 lf.emit.root_dir.path orelse ".", lf.emit.sub_path,4450 lf.emit.root_dir.path orelse ".", lf.emit.sub_path,
4557 }),4451 }),
4558 };4452 };
...@@ -4679,7 +4573,7 @@ fn cmdTranslateC(...@@ -4679,7 +4573,7 @@ fn cmdTranslateC(
4679 },4573 },
4680 }4574 }
46814575
4682 var zig_cache_tmp_dir = try comp.local_cache_directory.handle.makeOpenPath("tmp", .{});4576 var zig_cache_tmp_dir = try comp.dirs.local_cache.handle.makeOpenPath("tmp", .{});
4683 defer zig_cache_tmp_dir.close();4577 defer zig_cache_tmp_dir.close();
46844578
4685 const ext = Compilation.classifyFileExt(c_source_file.src_path);4579 const ext = Compilation.classifyFileExt(c_source_file.src_path);
...@@ -4735,7 +4629,7 @@ fn cmdTranslateC(...@@ -4735,7 +4629,7 @@ fn cmdTranslateC(
4735 new_argv[argv.items.len + i] = try arena.dupeZ(u8, arg);4629 new_argv[argv.items.len + i] = try arena.dupeZ(u8, arg);
4736 }4630 }
47374631
4738 const c_headers_dir_path_z = try comp.zig_lib_directory.joinZ(arena, &[_][]const u8{"include"});4632 const c_headers_dir_path_z = try comp.dirs.zig_lib.joinZ(arena, &.{"include"});
4739 var errors = std.zig.ErrorBundle.empty;4633 var errors = std.zig.ErrorBundle.empty;
4740 var tree = translate_c.translate(4634 var tree = translate_c.translate(
4741 comp.gpa,4635 comp.gpa,
...@@ -4787,7 +4681,7 @@ fn cmdTranslateC(...@@ -4787,7 +4681,7 @@ fn cmdTranslateC(
47874681
4788 const o_sub_path = try fs.path.join(arena, &[_][]const u8{ "o", &hex_digest });4682 const o_sub_path = try fs.path.join(arena, &[_][]const u8{ "o", &hex_digest });
47894683
4790 var o_dir = try comp.local_cache_directory.handle.makeOpenPath(o_sub_path, .{});4684 var o_dir = try comp.dirs.local_cache.handle.makeOpenPath(o_sub_path, .{});
4791 defer o_dir.close();4685 defer o_dir.close();
47924686
4793 var zig_file = try o_dir.createFile(translated_zig_basename, .{});4687 var zig_file = try o_dir.createFile(translated_zig_basename, .{});
...@@ -4808,9 +4702,9 @@ fn cmdTranslateC(...@@ -4808,9 +4702,9 @@ fn cmdTranslateC(
4808 p.digest = bin_digest;4702 p.digest = bin_digest;
4809 p.errors = std.zig.ErrorBundle.empty;4703 p.errors = std.zig.ErrorBundle.empty;
4810 } else {4704 } else {
4811 const out_zig_path = try fs.path.join(arena, &[_][]const u8{ "o", &hex_digest, translated_zig_basename });4705 const out_zig_path = try fs.path.join(arena, &.{ "o", &hex_digest, translated_zig_basename });
4812 const zig_file = comp.local_cache_directory.handle.openFile(out_zig_path, .{}) catch |err| {4706 const zig_file = comp.dirs.local_cache.handle.openFile(out_zig_path, .{}) catch |err| {
4813 const path = comp.local_cache_directory.path orelse ".";4707 const path = comp.dirs.local_cache.path orelse ".";
4814 fatal("unable to open cached translated zig file '{s}{s}{s}': {s}", .{ path, fs.path.sep_str, out_zig_path, @errorName(err) });4708 fatal("unable to open cached translated zig file '{s}{s}{s}': {s}", .{ path, fs.path.sep_str, out_zig_path, @errorName(err) });
4815 };4709 };
4816 defer zig_file.close();4710 defer zig_file.close();
...@@ -4854,7 +4748,7 @@ fn cmdInit(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {...@@ -4854,7 +4748,7 @@ fn cmdInit(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
4854 var templates = findTemplates(gpa, arena);4748 var templates = findTemplates(gpa, arena);
4855 defer templates.deinit();4749 defer templates.deinit();
48564750
4857 const cwd_path = try process.getCwdAlloc(arena);4751 const cwd_path = try introspect.getResolvedCwd(arena);
4858 const cwd_basename = fs.path.basename(cwd_path);4752 const cwd_basename = fs.path.basename(cwd_path);
4859 const sanitized_root_name = try sanitizeExampleName(arena, cwd_basename);4753 const sanitized_root_name = try sanitizeExampleName(arena, cwd_basename);
48604754
...@@ -4952,7 +4846,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {...@@ -4952,7 +4846,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
4952 const argv_index_exe = child_argv.items.len;4846 const argv_index_exe = child_argv.items.len;
4953 _ = try child_argv.addOne();4847 _ = try child_argv.addOne();
49544848
4955 const self_exe_path = try introspect.findZigExePath(arena);4849 const self_exe_path = try fs.selfExePathAlloc(arena);
4956 try child_argv.append(self_exe_path);4850 try child_argv.append(self_exe_path);
49574851
4958 const argv_index_zig_lib_dir = child_argv.items.len;4852 const argv_index_zig_lib_dir = child_argv.items.len;
...@@ -5169,60 +5063,30 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {...@@ -5169,60 +5063,30 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
51695063
5170 process.raiseFileDescriptorLimit();5064 process.raiseFileDescriptorLimit();
51715065
5172 var zig_lib_directory: Directory = if (override_lib_dir) |lib_dir| .{5066 const cwd_path = try introspect.getResolvedCwd(arena);
5173 .path = lib_dir,
5174 .handle = fs.cwd().openDir(lib_dir, .{}) catch |err| {
5175 fatal("unable to open zig lib directory from 'zig-lib-dir' argument: '{s}': {s}", .{ lib_dir, @errorName(err) });
5176 },
5177 } else introspect.findZigLibDirFromSelfExe(arena, self_exe_path) catch |err| {
5178 fatal("unable to find zig installation directory '{s}': {s}", .{ self_exe_path, @errorName(err) });
5179 };
5180 defer zig_lib_directory.handle.close();
5181
5182 const cwd_path = try process.getCwdAlloc(arena);
5183 child_argv.items[argv_index_zig_lib_dir] = zig_lib_directory.path orelse cwd_path;
5184
5185 const build_root = try findBuildRoot(arena, .{5067 const build_root = try findBuildRoot(arena, .{
5186 .cwd_path = cwd_path,5068 .cwd_path = cwd_path,
5187 .build_file = build_file,5069 .build_file = build_file,
5188 });5070 });
5189 child_argv.items[argv_index_build_file] = build_root.directory.path orelse cwd_path;
5190
5191 var global_cache_directory: Directory = l: {
5192 const p = override_global_cache_dir orelse try introspect.resolveGlobalCacheDir(arena);
5193 const dir = fs.cwd().makeOpenPath(p, .{}) catch |err| {
5194 const base_msg = "unable to open or create the global Zig cache at '{s}': {s}.{s}";
5195 const extra = "\nIf this location is not writable then consider specifying an " ++
5196 "alternative with the ZIG_GLOBAL_CACHE_DIR environment variable or the " ++
5197 "--global-cache-dir option.";
5198 const show_extra = err == error.AccessDenied or err == error.ReadOnlyFileSystem;
5199 fatal(base_msg, .{ p, @errorName(err), if (show_extra) extra else "" });
5200 };
5201 break :l .{
5202 .handle = dir,
5203 .path = p,
5204 };
5205 };
5206 defer global_cache_directory.handle.close();
52075071
5208 child_argv.items[argv_index_global_cache_dir] = global_cache_directory.path orelse cwd_path;5072 // This `init` calls `fatal` on error.
52095073 var dirs: Compilation.Directories = .init(
5210 var local_cache_directory: Directory = l: {5074 arena,
5211 if (override_local_cache_dir) |local_cache_dir_path| {5075 override_lib_dir,
5212 break :l .{5076 override_global_cache_dir,
5213 .handle = try fs.cwd().makeOpenPath(local_cache_dir_path, .{}),5077 .{ .override = path: {
5214 .path = local_cache_dir_path,5078 if (override_local_cache_dir) |d| break :path d;
5215 };5079 break :path try build_root.directory.join(arena, &.{introspect.default_local_zig_cache_basename});
5216 }5080 } },
5217 const cache_dir_path = try build_root.directory.join(arena, &.{default_local_zig_cache_basename});5081 {},
5218 break :l .{5082 self_exe_path,
5219 .handle = try build_root.directory.handle.makeOpenPath(default_local_zig_cache_basename, .{}),5083 );
5220 .path = cache_dir_path,5084 defer dirs.deinit();
5221 };
5222 };
5223 defer local_cache_directory.handle.close();
52245085
5225 child_argv.items[argv_index_cache_dir] = local_cache_directory.path orelse cwd_path;5086 child_argv.items[argv_index_zig_lib_dir] = dirs.zig_lib.path orelse cwd_path;
5087 child_argv.items[argv_index_build_file] = build_root.directory.path orelse cwd_path;
5088 child_argv.items[argv_index_global_cache_dir] = dirs.global_cache.path orelse cwd_path;
5089 child_argv.items[argv_index_cache_dir] = dirs.local_cache.path orelse cwd_path;
52265090
5227 var thread_pool: ThreadPool = undefined;5091 var thread_pool: ThreadPool = undefined;
5228 try thread_pool.init(.{5092 try thread_pool.init(.{
...@@ -5250,16 +5114,10 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {...@@ -5250,16 +5114,10 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
5250 // big block here to ensure the cleanup gets run when we extract out our argv.5114 // big block here to ensure the cleanup gets run when we extract out our argv.
5251 {5115 {
5252 const main_mod_paths: Package.Module.CreateOptions.Paths = if (override_build_runner) |runner| .{5116 const main_mod_paths: Package.Module.CreateOptions.Paths = if (override_build_runner) |runner| .{
5253 .root = .{5117 .root = try .fromUnresolved(arena, dirs, &.{fs.path.dirname(runner) orelse "."}),
5254 .root_dir = Cache.Directory.cwd(),
5255 .sub_path = fs.path.dirname(runner) orelse "",
5256 },
5257 .root_src_path = fs.path.basename(runner),5118 .root_src_path = fs.path.basename(runner),
5258 } else .{5119 } else .{
5259 .root = .{5120 .root = try .fromRoot(arena, dirs, .zig_lib, "compiler"),
5260 .root_dir = zig_lib_directory,
5261 .sub_path = "compiler",
5262 },
5263 .root_src_path = "build_runner.zig",5121 .root_src_path = "build_runner.zig",
5264 };5122 };
52655123
...@@ -5272,7 +5130,6 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {...@@ -5272,7 +5130,6 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
5272 });5130 });
52735131
5274 const root_mod = try Package.Module.create(arena, .{5132 const root_mod = try Package.Module.create(arena, .{
5275 .global_cache_directory = global_cache_directory,
5276 .paths = main_mod_paths,5133 .paths = main_mod_paths,
5277 .fully_qualified_name = "root",5134 .fully_qualified_name = "root",
5278 .cc_argv = &.{},5135 .cc_argv = &.{},
...@@ -5281,16 +5138,11 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {...@@ -5281,16 +5138,11 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
5281 },5138 },
5282 .global = config,5139 .global = config,
5283 .parent = null,5140 .parent = null,
5284 .builtin_mod = null,
5285 .builtin_modules = null, // all modules will inherit this one's builtin
5286 });5141 });
52875142
5288 const builtin_mod = root_mod.getBuiltinDependency();
5289
5290 const build_mod = try Package.Module.create(arena, .{5143 const build_mod = try Package.Module.create(arena, .{
5291 .global_cache_directory = global_cache_directory,
5292 .paths = .{5144 .paths = .{
5293 .root = .{ .root_dir = build_root.directory },5145 .root = try .fromUnresolved(arena, dirs, &.{build_root.directory.path orelse "."}),
5294 .root_src_path = build_root.build_zig_basename,5146 .root_src_path = build_root.build_zig_basename,
5295 },5147 },
5296 .fully_qualified_name = "root.@build",5148 .fully_qualified_name = "root.@build",
...@@ -5298,8 +5150,6 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {...@@ -5298,8 +5150,6 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
5298 .inherited = .{},5150 .inherited = .{},
5299 .global = config,5151 .global = config,
5300 .parent = root_mod,5152 .parent = root_mod,
5301 .builtin_mod = builtin_mod,
5302 .builtin_modules = null, // `builtin_mod` is specified
5303 });5153 });
53045154
5305 var cleanup_build_dir: ?fs.Dir = null;5155 var cleanup_build_dir: ?fs.Dir = null;
...@@ -5312,7 +5162,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {...@@ -5312,7 +5162,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
5312 var job_queue: Package.Fetch.JobQueue = .{5162 var job_queue: Package.Fetch.JobQueue = .{
5313 .http_client = &http_client,5163 .http_client = &http_client,
5314 .thread_pool = &thread_pool,5164 .thread_pool = &thread_pool,
5315 .global_cache = global_cache_directory,5165 .global_cache = dirs.global_cache,
5316 .read_only = false,5166 .read_only = false,
5317 .recursive = true,5167 .recursive = true,
5318 .debug_hash = false,5168 .debug_hash = false,
...@@ -5340,14 +5190,16 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {...@@ -5340,14 +5190,16 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
5340 try job_queue.all_fetches.ensureUnusedCapacity(gpa, 1);5190 try job_queue.all_fetches.ensureUnusedCapacity(gpa, 1);
5341 try job_queue.table.ensureUnusedCapacity(gpa, 1);5191 try job_queue.table.ensureUnusedCapacity(gpa, 1);
53425192
5193 const phantom_package_root: Cache.Path = .{ .root_dir = build_root.directory };
5194
5343 var fetch: Package.Fetch = .{5195 var fetch: Package.Fetch = .{
5344 .arena = std.heap.ArenaAllocator.init(gpa),5196 .arena = std.heap.ArenaAllocator.init(gpa),
5345 .location = .{ .relative_path = build_mod.root },5197 .location = .{ .relative_path = phantom_package_root },
5346 .location_tok = 0,5198 .location_tok = 0,
5347 .hash_tok = .none,5199 .hash_tok = .none,
5348 .name_tok = 0,5200 .name_tok = 0,
5349 .lazy_status = .eager,5201 .lazy_status = .eager,
5350 .parent_package_root = build_mod.root,5202 .parent_package_root = phantom_package_root,
5351 .parent_manifest_ast = null,5203 .parent_manifest_ast = null,
5352 .prog_node = fetch_prog_node,5204 .prog_node = fetch_prog_node,
5353 .job_queue = &job_queue,5205 .job_queue = &job_queue,
...@@ -5371,7 +5223,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {...@@ -5371,7 +5223,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
5371 job_queue.all_fetches.appendAssumeCapacity(&fetch);5223 job_queue.all_fetches.appendAssumeCapacity(&fetch);
53725224
5373 job_queue.table.putAssumeCapacityNoClobber(5225 job_queue.table.putAssumeCapacityNoClobber(
5374 Package.Fetch.relativePathDigest(build_mod.root, global_cache_directory),5226 Package.Fetch.relativePathDigest(phantom_package_root, dirs.global_cache),
5375 &fetch,5227 &fetch,
5376 );5228 );
53775229
...@@ -5397,9 +5249,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {...@@ -5397,9 +5249,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
5397 arena,5249 arena,
5398 source_buf.items,5250 source_buf.items,
5399 root_mod,5251 root_mod,
5400 global_cache_directory,5252 dirs,
5401 local_cache_directory,
5402 builtin_mod,
5403 config,5253 config,
5404 );5254 );
54055255
...@@ -5416,10 +5266,10 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {...@@ -5416,10 +5266,10 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
5416 if (!f.has_build_zig)5266 if (!f.has_build_zig)
5417 continue;5267 continue;
5418 const hash_slice = hash.toSlice();5268 const hash_slice = hash.toSlice();
5269 const mod_root_path = try f.package_root.toString(arena);
5419 const m = try Package.Module.create(arena, .{5270 const m = try Package.Module.create(arena, .{
5420 .global_cache_directory = global_cache_directory,
5421 .paths = .{5271 .paths = .{
5422 .root = try f.package_root.clone(arena),5272 .root = try .fromUnresolved(arena, dirs, &.{mod_root_path}),
5423 .root_src_path = Package.build_zig_basename,5273 .root_src_path = Package.build_zig_basename,
5424 },5274 },
5425 .fully_qualified_name = try std.fmt.allocPrint(5275 .fully_qualified_name = try std.fmt.allocPrint(
...@@ -5431,8 +5281,6 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {...@@ -5431,8 +5281,6 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
5431 .inherited = .{},5281 .inherited = .{},
5432 .global = config,5282 .global = config,
5433 .parent = root_mod,5283 .parent = root_mod,
5434 .builtin_mod = builtin_mod,
5435 .builtin_modules = null, // `builtin_mod` is specified
5436 });5284 });
5437 const hash_cloned = try arena.dupe(u8, hash_slice);5285 const hash_cloned = try arena.dupe(u8, hash_slice);
5438 deps_mod.deps.putAssumeCapacityNoClobber(hash_cloned, m);5286 deps_mod.deps.putAssumeCapacityNoClobber(hash_cloned, m);
...@@ -5449,7 +5297,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {...@@ -5449,7 +5297,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
5449 for (dep_names, man.dependencies.values()) |name, dep| {5297 for (dep_names, man.dependencies.values()) |name, dep| {
5450 const dep_digest = Package.Fetch.depDigest(5298 const dep_digest = Package.Fetch.depDigest(
5451 f.package_root,5299 f.package_root,
5452 global_cache_directory,5300 dirs.global_cache,
5453 dep,5301 dep,
5454 ) orelse continue;5302 ) orelse continue;
5455 const dep_mod = job_queue.table.get(dep_digest).?.module orelse continue;5303 const dep_mod = job_queue.table.get(dep_digest).?.module orelse continue;
...@@ -5461,18 +5309,14 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {...@@ -5461,18 +5309,14 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
5461 } else try createEmptyDependenciesModule(5309 } else try createEmptyDependenciesModule(
5462 arena,5310 arena,
5463 root_mod,5311 root_mod,
5464 global_cache_directory,5312 dirs,
5465 local_cache_directory,
5466 builtin_mod,
5467 config,5313 config,
5468 );5314 );
54695315
5470 try root_mod.deps.put(arena, "@build", build_mod);5316 try root_mod.deps.put(arena, "@build", build_mod);
54715317
5472 const comp = Compilation.create(gpa, arena, .{5318 const comp = Compilation.create(gpa, arena, .{
5473 .zig_lib_directory = zig_lib_directory,5319 .dirs = dirs,
5474 .local_cache_directory = local_cache_directory,
5475 .global_cache_directory = global_cache_directory,
5476 .root_name = "build",5320 .root_name = "build",
5477 .config = config,5321 .config = config,
5478 .root_mod = root_mod,5322 .root_mod = root_mod,
...@@ -5507,7 +5351,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {...@@ -5507,7 +5351,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
5507 // above, and thus the output file is already closed.5351 // above, and thus the output file is already closed.
5508 //try comp.makeBinFileExecutable();5352 //try comp.makeBinFileExecutable();
5509 child_argv.items[argv_index_exe] =5353 child_argv.items[argv_index_exe] =
5510 try local_cache_directory.join(arena, &.{comp.cache_use.whole.bin_sub_path.?});5354 try dirs.local_cache.join(arena, &.{comp.cache_use.whole.bin_sub_path.?});
5511 }5355 }
55125356
5513 if (process.can_spawn) {5357 if (process.can_spawn) {
...@@ -5539,12 +5383,12 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {...@@ -5539,12 +5383,12 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
5539 // that are missing.5383 // that are missing.
5540 const s = fs.path.sep_str;5384 const s = fs.path.sep_str;
5541 const tmp_sub_path = "tmp" ++ s ++ results_tmp_file_nonce;5385 const tmp_sub_path = "tmp" ++ s ++ results_tmp_file_nonce;
5542 const stdout = local_cache_directory.handle.readFileAlloc(arena, tmp_sub_path, 50 * 1024 * 1024) catch |err| {5386 const stdout = dirs.local_cache.handle.readFileAlloc(arena, tmp_sub_path, 50 * 1024 * 1024) catch |err| {
5543 fatal("unable to read results of configure phase from '{}{s}': {s}", .{5387 fatal("unable to read results of configure phase from '{}{s}': {s}", .{
5544 local_cache_directory, tmp_sub_path, @errorName(err),5388 dirs.local_cache, tmp_sub_path, @errorName(err),
5545 });5389 });
5546 };5390 };
5547 local_cache_directory.handle.deleteFile(tmp_sub_path) catch {};5391 dirs.local_cache.handle.deleteFile(tmp_sub_path) catch {};
55485392
5549 var it = mem.splitScalar(u8, stdout, '\n');5393 var it = mem.splitScalar(u8, stdout, '\n');
5550 var any_errors = false;5394 var any_errors = false;
...@@ -5633,7 +5477,7 @@ fn jitCmd(...@@ -5633,7 +5477,7 @@ fn jitCmd(
5633 .basename = exe_basename,5477 .basename = exe_basename,
5634 };5478 };
56355479
5636 const self_exe_path = introspect.findZigExePath(arena) catch |err| {5480 const self_exe_path = fs.selfExePathAlloc(arena) catch |err| {
5637 fatal("unable to find self exe path: {s}", .{@errorName(err)});5481 fatal("unable to find self exe path: {s}", .{@errorName(err)});
5638 };5482 };
56395483
...@@ -5645,24 +5489,16 @@ fn jitCmd(...@@ -5645,24 +5489,16 @@ fn jitCmd(
5645 const override_lib_dir: ?[]const u8 = try EnvVar.ZIG_LIB_DIR.get(arena);5489 const override_lib_dir: ?[]const u8 = try EnvVar.ZIG_LIB_DIR.get(arena);
5646 const override_global_cache_dir: ?[]const u8 = try EnvVar.ZIG_GLOBAL_CACHE_DIR.get(arena);5490 const override_global_cache_dir: ?[]const u8 = try EnvVar.ZIG_GLOBAL_CACHE_DIR.get(arena);
56475491
5648 var zig_lib_directory: Directory = if (override_lib_dir) |lib_dir| .{5492 // This `init` calls `fatal` on error.
5649 .path = lib_dir,5493 var dirs: Compilation.Directories = .init(
5650 .handle = fs.cwd().openDir(lib_dir, .{}) catch |err| {5494 arena,
5651 fatal("unable to open zig lib directory from 'zig-lib-dir' argument: '{s}': {s}", .{ lib_dir, @errorName(err) });5495 override_lib_dir,
5652 },5496 override_global_cache_dir,
5653 } else introspect.findZigLibDirFromSelfExe(arena, self_exe_path) catch |err| {5497 .global,
5654 fatal("unable to find zig installation directory '{s}': {s}", .{ self_exe_path, @errorName(err) });5498 if (native_os == .wasi) wasi_preopens,
5655 };5499 self_exe_path,
5656 defer zig_lib_directory.handle.close();5500 );
56575501 defer dirs.deinit();
5658 var global_cache_directory: Directory = l: {
5659 const p = override_global_cache_dir orelse try introspect.resolveGlobalCacheDir(arena);
5660 break :l .{
5661 .handle = try fs.cwd().makeOpenPath(p, .{}),
5662 .path = p,
5663 };
5664 };
5665 defer global_cache_directory.handle.close();
56665502
5667 var thread_pool: ThreadPool = undefined;5503 var thread_pool: ThreadPool = undefined;
5668 try thread_pool.init(.{5504 try thread_pool.init(.{
...@@ -5680,10 +5516,7 @@ fn jitCmd(...@@ -5680,10 +5516,7 @@ fn jitCmd(
5680 // big block here to ensure the cleanup gets run when we extract out our argv.5516 // big block here to ensure the cleanup gets run when we extract out our argv.
5681 {5517 {
5682 const main_mod_paths: Package.Module.CreateOptions.Paths = .{5518 const main_mod_paths: Package.Module.CreateOptions.Paths = .{
5683 .root = .{5519 .root = try .fromRoot(arena, dirs, .zig_lib, "compiler"),
5684 .root_dir = zig_lib_directory,
5685 .sub_path = "compiler",
5686 },
5687 .root_src_path = options.root_src_path,5520 .root_src_path = options.root_src_path,
5688 };5521 };
56895522
...@@ -5698,7 +5531,6 @@ fn jitCmd(...@@ -5698,7 +5531,6 @@ fn jitCmd(
5698 });5531 });
56995532
5700 const root_mod = try Package.Module.create(arena, .{5533 const root_mod = try Package.Module.create(arena, .{
5701 .global_cache_directory = global_cache_directory,
5702 .paths = main_mod_paths,5534 .paths = main_mod_paths,
5703 .fully_qualified_name = "root",5535 .fully_qualified_name = "root",
5704 .cc_argv = &.{},5536 .cc_argv = &.{},
...@@ -5709,18 +5541,12 @@ fn jitCmd(...@@ -5709,18 +5541,12 @@ fn jitCmd(
5709 },5541 },
5710 .global = config,5542 .global = config,
5711 .parent = null,5543 .parent = null,
5712 .builtin_mod = null,
5713 .builtin_modules = null, // all modules will inherit this one's builtin
5714 });5544 });
57155545
5716 if (options.depend_on_aro) {5546 if (options.depend_on_aro) {
5717 const aro_mod = try Package.Module.create(arena, .{5547 const aro_mod = try Package.Module.create(arena, .{
5718 .global_cache_directory = global_cache_directory,
5719 .paths = .{5548 .paths = .{
5720 .root = .{5549 .root = try .fromRoot(arena, dirs, .zig_lib, "compiler/aro"),
5721 .root_dir = zig_lib_directory,
5722 .sub_path = "compiler/aro",
5723 },
5724 .root_src_path = "aro.zig",5550 .root_src_path = "aro.zig",
5725 },5551 },
5726 .fully_qualified_name = "aro",5552 .fully_qualified_name = "aro",
...@@ -5732,16 +5558,12 @@ fn jitCmd(...@@ -5732,16 +5558,12 @@ fn jitCmd(
5732 },5558 },
5733 .global = config,5559 .global = config,
5734 .parent = null,5560 .parent = null,
5735 .builtin_mod = root_mod.getBuiltinDependency(),
5736 .builtin_modules = null, // `builtin_mod` is specified
5737 });5561 });
5738 try root_mod.deps.put(arena, "aro", aro_mod);5562 try root_mod.deps.put(arena, "aro", aro_mod);
5739 }5563 }
57405564
5741 const comp = Compilation.create(gpa, arena, .{5565 const comp = Compilation.create(gpa, arena, .{
5742 .zig_lib_directory = zig_lib_directory,5566 .dirs = dirs,
5743 .local_cache_directory = global_cache_directory,
5744 .global_cache_directory = global_cache_directory,
5745 .root_name = options.cmd_name,5567 .root_name = options.cmd_name,
5746 .config = config,5568 .config = config,
5747 .root_mod = root_mod,5569 .root_mod = root_mod,
...@@ -5778,16 +5600,16 @@ fn jitCmd(...@@ -5778,16 +5600,16 @@ fn jitCmd(
5778 };5600 };
5779 }5601 }
57805602
5781 const exe_path = try global_cache_directory.join(arena, &.{comp.cache_use.whole.bin_sub_path.?});5603 const exe_path = try dirs.global_cache.join(arena, &.{comp.cache_use.whole.bin_sub_path.?});
5782 child_argv.appendAssumeCapacity(exe_path);5604 child_argv.appendAssumeCapacity(exe_path);
5783 }5605 }
57845606
5785 if (options.prepend_zig_lib_dir_path)5607 if (options.prepend_zig_lib_dir_path)
5786 child_argv.appendAssumeCapacity(zig_lib_directory.path.?);5608 child_argv.appendAssumeCapacity(dirs.zig_lib.path.?);
5787 if (options.prepend_zig_exe_path)5609 if (options.prepend_zig_exe_path)
5788 child_argv.appendAssumeCapacity(self_exe_path);5610 child_argv.appendAssumeCapacity(self_exe_path);
5789 if (options.prepend_global_cache_path)5611 if (options.prepend_global_cache_path)
5790 child_argv.appendAssumeCapacity(global_cache_directory.path.?);5612 child_argv.appendAssumeCapacity(dirs.global_cache.path.?);
57915613
5792 child_argv.appendSliceAssumeCapacity(args);5614 child_argv.appendSliceAssumeCapacity(args);
57935615
...@@ -6270,7 +6092,6 @@ const usage_ast_check =...@@ -6270,7 +6092,6 @@ const usage_ast_check =
6270;6092;
62716093
6272fn cmdAstCheck(6094fn cmdAstCheck(
6273 gpa: Allocator,
6274 arena: Allocator,6095 arena: Allocator,
6275 args: []const []const u8,6096 args: []const []const u8,
6276) !void {6097) !void {
...@@ -6281,7 +6102,7 @@ fn cmdAstCheck(...@@ -6281,7 +6102,7 @@ fn cmdAstCheck(
6281 var color: Color = .auto;6102 var color: Color = .auto;
6282 var want_output_text = false;6103 var want_output_text = false;
6283 var force_zon = false;6104 var force_zon = false;
6284 var zig_source_file: ?[]const u8 = null;6105 var zig_source_path: ?[]const u8 = null;
62856106
6286 var i: usize = 0;6107 var i: usize = 0;
6287 while (i < args.len) : (i += 1) {6108 while (i < args.len) : (i += 1) {
...@@ -6306,96 +6127,55 @@ fn cmdAstCheck(...@@ -6306,96 +6127,55 @@ fn cmdAstCheck(
6306 } else {6127 } else {
6307 fatal("unrecognized parameter: '{s}'", .{arg});6128 fatal("unrecognized parameter: '{s}'", .{arg});
6308 }6129 }
6309 } else if (zig_source_file == null) {6130 } else if (zig_source_path == null) {
6310 zig_source_file = arg;6131 zig_source_path = arg;
6311 } else {6132 } else {
6312 fatal("extra positional parameter: '{s}'", .{arg});6133 fatal("extra positional parameter: '{s}'", .{arg});
6313 }6134 }
6314 }6135 }
63156136
6316 var file: Zcu.File = .{6137 const display_path = zig_source_path orelse "<stdin>";
6317 .status = .never_loaded,6138 const source: [:0]const u8 = s: {
6318 .sub_file_path = undefined,6139 var f = if (zig_source_path) |p| file: {
6319 .stat = undefined,6140 break :file fs.cwd().openFile(p, .{}) catch |err| {
6320 .source = null,6141 fatal("unable to open file '{s}' for ast-check: {s}", .{ display_path, @errorName(err) });
6321 .tree = null,6142 };
6322 .zir = null,6143 } else io.getStdIn();
6323 .zoir = null,6144 defer if (zig_source_path != null) f.close();
6324 .mod = undefined,6145 break :s std.zig.readSourceFileToEndAlloc(arena, f, null) catch |err| {
6325 };6146 fatal("unable to load file '{s}' for ast-check: {s}", .{ display_path, @errorName(err) });
6326 if (zig_source_file) |file_name| {
6327 var f = fs.cwd().openFile(file_name, .{}) catch |err| {
6328 fatal("unable to open file for ast-check '{s}': {s}", .{ file_name, @errorName(err) });
6329 };
6330 defer f.close();
6331
6332 const stat = try f.stat();
6333
6334 if (stat.size > std.zig.max_src_size)
6335 return error.FileTooBig;
6336
6337 const source = try arena.allocSentinel(u8, @as(usize, @intCast(stat.size)), 0);
6338 const amt = try f.readAll(source);
6339 if (amt != stat.size)
6340 return error.UnexpectedEndOfFile;
6341
6342 file.sub_file_path = file_name;
6343 file.source = source;
6344 file.stat = .{
6345 .size = stat.size,
6346 .inode = stat.inode,
6347 .mtime = stat.mtime,
6348 };
6349 } else {
6350 const stdin = io.getStdIn();
6351 const source = std.zig.readSourceFileToEndAlloc(arena, stdin, null) catch |err| {
6352 fatal("unable to read stdin: {}", .{err});
6353 };6147 };
6354 file.sub_file_path = "<stdin>";6148 };
6355 file.source = source;
6356 file.stat.size = source.len;
6357 }
63586149
6359 const mode: Ast.Mode = mode: {6150 const mode: Ast.Mode = mode: {
6360 if (force_zon) break :mode .zon;6151 if (force_zon) break :mode .zon;
6361 if (zig_source_file) |name| {6152 if (zig_source_path) |path| {
6362 if (mem.endsWith(u8, name, ".zon")) {6153 if (mem.endsWith(u8, path, ".zon")) {
6363 break :mode .zon;6154 break :mode .zon;
6364 }6155 }
6365 }6156 }
6366 break :mode .zig;6157 break :mode .zig;
6367 };6158 };
63686159
6369 file.mod = try Package.Module.createLimited(arena, .{6160 const tree = try Ast.parse(arena, source, mode);
6370 .root = Path.cwd(),
6371 .root_src_path = file.sub_file_path,
6372 .fully_qualified_name = "root",
6373 });
6374
6375 file.tree = try Ast.parse(gpa, file.source.?, mode);
6376 defer file.tree.?.deinit(gpa);
63776161
6378 switch (mode) {6162 switch (mode) {
6379 .zig => {6163 .zig => {
6380 file.zir = try AstGen.generate(gpa, file.tree.?);6164 const zir = try AstGen.generate(arena, tree);
6381 defer file.zir.?.deinit(gpa);
63826165
6383 if (file.zir.?.hasCompileErrors()) {6166 if (zir.hasCompileErrors()) {
6384 var wip_errors: std.zig.ErrorBundle.Wip = undefined;6167 var wip_errors: std.zig.ErrorBundle.Wip = undefined;
6385 try wip_errors.init(gpa);6168 try wip_errors.init(arena);
6386 defer wip_errors.deinit();6169 try wip_errors.addZirErrorMessages(zir, tree, source, display_path);
6387 try Compilation.addZirErrorMessages(&wip_errors, &file);
6388 var error_bundle = try wip_errors.toOwnedBundle("");6170 var error_bundle = try wip_errors.toOwnedBundle("");
6389 defer error_bundle.deinit(gpa);
6390 error_bundle.renderToStdErr(color.renderOptions());6171 error_bundle.renderToStdErr(color.renderOptions());
63916172 if (zir.loweringFailed()) {
6392 if (file.zir.?.loweringFailed()) {
6393 process.exit(1);6173 process.exit(1);
6394 }6174 }
6395 }6175 }
63966176
6397 if (!want_output_text) {6177 if (!want_output_text) {
6398 if (file.zir.?.hasCompileErrors()) {6178 if (zir.hasCompileErrors()) {
6399 process.exit(1);6179 process.exit(1);
6400 } else {6180 } else {
6401 return cleanExit();6181 return cleanExit();
...@@ -6407,20 +6187,20 @@ fn cmdAstCheck(...@@ -6407,20 +6187,20 @@ fn cmdAstCheck(
64076187
6408 {6188 {
6409 const token_bytes = @sizeOf(Ast.TokenList) +6189 const token_bytes = @sizeOf(Ast.TokenList) +
6410 file.tree.?.tokens.len * (@sizeOf(std.zig.Token.Tag) + @sizeOf(Ast.ByteOffset));6190 tree.tokens.len * (@sizeOf(std.zig.Token.Tag) + @sizeOf(Ast.ByteOffset));
6411 const tree_bytes = @sizeOf(Ast) + file.tree.?.nodes.len *6191 const tree_bytes = @sizeOf(Ast) + tree.nodes.len *
6412 (@sizeOf(Ast.Node.Tag) +6192 (@sizeOf(Ast.Node.Tag) +
6413 @sizeOf(Ast.TokenIndex) +6193 @sizeOf(Ast.TokenIndex) +
6414 // Here we don't use @sizeOf(Ast.Node.Data) because it would include6194 // Here we don't use @sizeOf(Ast.Node.Data) because it would include
6415 // the debug safety tag but we want to measure release size.6195 // the debug safety tag but we want to measure release size.
6416 8);6196 8);
6417 const instruction_bytes = file.zir.?.instructions.len *6197 const instruction_bytes = zir.instructions.len *
6418 // Here we don't use @sizeOf(Zir.Inst.Data) because it would include6198 // Here we don't use @sizeOf(Zir.Inst.Data) because it would include
6419 // the debug safety tag but we want to measure release size.6199 // the debug safety tag but we want to measure release size.
6420 (@sizeOf(Zir.Inst.Tag) + 8);6200 (@sizeOf(Zir.Inst.Tag) + 8);
6421 const extra_bytes = file.zir.?.extra.len * @sizeOf(u32);6201 const extra_bytes = zir.extra.len * @sizeOf(u32);
6422 const total_bytes = @sizeOf(Zir) + instruction_bytes + extra_bytes +6202 const total_bytes = @sizeOf(Zir) + instruction_bytes + extra_bytes +
6423 file.zir.?.string_bytes.len * @sizeOf(u8);6203 zir.string_bytes.len * @sizeOf(u8);
6424 const stdout = io.getStdOut();6204 const stdout = io.getStdOut();
6425 const fmtIntSizeBin = std.fmt.fmtIntSizeBin;6205 const fmtIntSizeBin = std.fmt.fmtIntSizeBin;
6426 // zig fmt: off6206 // zig fmt: off
...@@ -6434,44 +6214,33 @@ fn cmdAstCheck(...@@ -6434,44 +6214,33 @@ fn cmdAstCheck(
6434 \\# Extra Data Items: {d} ({})6214 \\# Extra Data Items: {d} ({})
6435 \\6215 \\
6436 , .{6216 , .{
6437 fmtIntSizeBin(file.source.?.len),6217 fmtIntSizeBin(source.len),
6438 file.tree.?.tokens.len, fmtIntSizeBin(token_bytes),6218 tree.tokens.len, fmtIntSizeBin(token_bytes),
6439 file.tree.?.nodes.len, fmtIntSizeBin(tree_bytes),6219 tree.nodes.len, fmtIntSizeBin(tree_bytes),
6440 fmtIntSizeBin(total_bytes),6220 fmtIntSizeBin(total_bytes),
6441 file.zir.?.instructions.len, fmtIntSizeBin(instruction_bytes),6221 zir.instructions.len, fmtIntSizeBin(instruction_bytes),
6442 fmtIntSizeBin(file.zir.?.string_bytes.len),6222 fmtIntSizeBin(zir.string_bytes.len),
6443 file.zir.?.extra.len, fmtIntSizeBin(extra_bytes),6223 zir.extra.len, fmtIntSizeBin(extra_bytes),
6444 });6224 });
6445 // zig fmt: on6225 // zig fmt: on
6446 }6226 }
64476227
6448 try @import("print_zir.zig").renderAsTextToFile(gpa, &file, io.getStdOut());6228 try @import("print_zir.zig").renderAsTextToFile(arena, tree, zir, io.getStdOut());
64496229
6450 if (file.zir.?.hasCompileErrors()) {6230 if (zir.hasCompileErrors()) {
6451 process.exit(1);6231 process.exit(1);
6452 } else {6232 } else {
6453 return cleanExit();6233 return cleanExit();
6454 }6234 }
6455 },6235 },
6456 .zon => {6236 .zon => {
6457 const zoir = try ZonGen.generate(gpa, file.tree.?, .{});6237 const zoir = try ZonGen.generate(arena, tree, .{});
6458 defer zoir.deinit(gpa);
6459
6460 if (zoir.hasCompileErrors()) {6238 if (zoir.hasCompileErrors()) {
6461 var wip_errors: std.zig.ErrorBundle.Wip = undefined;6239 var wip_errors: std.zig.ErrorBundle.Wip = undefined;
6462 try wip_errors.init(gpa);6240 try wip_errors.init(arena);
6463 defer wip_errors.deinit();6241 try wip_errors.addZoirErrorMessages(zoir, tree, source, display_path);
6464
6465 {
6466 const src_path = try file.fullPath(gpa);
6467 defer gpa.free(src_path);
6468 try wip_errors.addZoirErrorMessages(zoir, file.tree.?, file.source.?, src_path);
6469 }
6470
6471 var error_bundle = try wip_errors.toOwnedBundle("");6242 var error_bundle = try wip_errors.toOwnedBundle("");
6472 defer error_bundle.deinit(gpa);
6473 error_bundle.renderToStdErr(color.renderOptions());6243 error_bundle.renderToStdErr(color.renderOptions());
6474
6475 process.exit(1);6244 process.exit(1);
6476 }6245 }
64776246
...@@ -6489,16 +6258,9 @@ fn cmdAstCheck(...@@ -6489,16 +6258,9 @@ fn cmdAstCheck(
6489 }6258 }
6490}6259}
64916260
6492fn cmdDetectCpu(6261fn cmdDetectCpu(args: []const []const u8) !void {
6493 gpa: Allocator,
6494 arena: Allocator,
6495 args: []const []const u8,
6496) !void {
6497 dev.check(.detect_cpu_command);6262 dev.check(.detect_cpu_command);
64986263
6499 _ = gpa;
6500 _ = arena;
6501
6502 const detect_cpu_usage =6264 const detect_cpu_usage =
6503 \\Usage: zig detect-cpu [--llvm]6265 \\Usage: zig detect-cpu [--llvm]
6504 \\6266 \\
...@@ -6676,13 +6438,11 @@ fn cmdDumpLlvmInts(...@@ -6676,13 +6438,11 @@ fn cmdDumpLlvmInts(
66766438
6677/// This is only enabled for debug builds.6439/// This is only enabled for debug builds.
6678fn cmdDumpZir(6440fn cmdDumpZir(
6679 gpa: Allocator,
6680 arena: Allocator,6441 arena: Allocator,
6681 args: []const []const u8,6442 args: []const []const u8,
6682) !void {6443) !void {
6683 dev.check(.dump_zir_command);6444 dev.check(.dump_zir_command);
66846445
6685 _ = arena;
6686 const Zir = std.zig.Zir;6446 const Zir = std.zig.Zir;
66876447
6688 const cache_file = args[0];6448 const cache_file = args[0];
...@@ -6692,26 +6452,16 @@ fn cmdDumpZir(...@@ -6692,26 +6452,16 @@ fn cmdDumpZir(
6692 };6452 };
6693 defer f.close();6453 defer f.close();
66946454
6695 var file: Zcu.File = .{6455 const zir = try Zcu.loadZirCache(arena, f);
6696 .status = .never_loaded,
6697 .sub_file_path = undefined,
6698 .stat = undefined,
6699 .source = null,
6700 .tree = null,
6701 .zir = try Zcu.loadZirCache(gpa, f),
6702 .zoir = null,
6703 .mod = undefined,
6704 };
6705 defer file.zir.?.deinit(gpa);
67066456
6707 {6457 {
6708 const instruction_bytes = file.zir.?.instructions.len *6458 const instruction_bytes = zir.instructions.len *
6709 // Here we don't use @sizeOf(Zir.Inst.Data) because it would include6459 // Here we don't use @sizeOf(Zir.Inst.Data) because it would include
6710 // the debug safety tag but we want to measure release size.6460 // the debug safety tag but we want to measure release size.
6711 (@sizeOf(Zir.Inst.Tag) + 8);6461 (@sizeOf(Zir.Inst.Tag) + 8);
6712 const extra_bytes = file.zir.?.extra.len * @sizeOf(u32);6462 const extra_bytes = zir.extra.len * @sizeOf(u32);
6713 const total_bytes = @sizeOf(Zir) + instruction_bytes + extra_bytes +6463 const total_bytes = @sizeOf(Zir) + instruction_bytes + extra_bytes +
6714 file.zir.?.string_bytes.len * @sizeOf(u8);6464 zir.string_bytes.len * @sizeOf(u8);
6715 const stdout = io.getStdOut();6465 const stdout = io.getStdOut();
6716 const fmtIntSizeBin = std.fmt.fmtIntSizeBin;6466 const fmtIntSizeBin = std.fmt.fmtIntSizeBin;
6717 // zig fmt: off6467 // zig fmt: off
...@@ -6723,19 +6473,18 @@ fn cmdDumpZir(...@@ -6723,19 +6473,18 @@ fn cmdDumpZir(
6723 \\6473 \\
6724 , .{6474 , .{
6725 fmtIntSizeBin(total_bytes),6475 fmtIntSizeBin(total_bytes),
6726 file.zir.?.instructions.len, fmtIntSizeBin(instruction_bytes),6476 zir.instructions.len, fmtIntSizeBin(instruction_bytes),
6727 fmtIntSizeBin(file.zir.?.string_bytes.len),6477 fmtIntSizeBin(zir.string_bytes.len),
6728 file.zir.?.extra.len, fmtIntSizeBin(extra_bytes),6478 zir.extra.len, fmtIntSizeBin(extra_bytes),
6729 });6479 });
6730 // zig fmt: on6480 // zig fmt: on
6731 }6481 }
67326482
6733 return @import("print_zir.zig").renderAsTextToFile(gpa, &file, io.getStdOut());6483 return @import("print_zir.zig").renderAsTextToFile(arena, null, zir, io.getStdOut());
6734}6484}
67356485
6736/// This is only enabled for debug builds.6486/// This is only enabled for debug builds.
6737fn cmdChangelist(6487fn cmdChangelist(
6738 gpa: Allocator,
6739 arena: Allocator,6488 arena: Allocator,
6740 args: []const []const u8,6489 args: []const []const u8,
6741) !void {6490) !void {
...@@ -6744,101 +6493,50 @@ fn cmdChangelist(...@@ -6744,101 +6493,50 @@ fn cmdChangelist(
6744 const color: Color = .auto;6493 const color: Color = .auto;
6745 const Zir = std.zig.Zir;6494 const Zir = std.zig.Zir;
67466495
6747 const old_source_file = args[0];6496 const old_source_path = args[0];
6748 const new_source_file = args[1];6497 const new_source_path = args[1];
67496498
6750 var f = fs.cwd().openFile(old_source_file, .{}) catch |err| {6499 const old_source = source: {
6751 fatal("unable to open old source file for comparison '{s}': {s}", .{ old_source_file, @errorName(err) });6500 var f = fs.cwd().openFile(old_source_path, .{}) catch |err|
6501 fatal("unable to open old source file '{s}': {s}", .{ old_source_path, @errorName(err) });
6502 defer f.close();
6503 break :source std.zig.readSourceFileToEndAlloc(arena, f, std.zig.max_src_size) catch |err|
6504 fatal("unable to read old source file '{s}': {s}", .{ old_source_path, @errorName(err) });
6752 };6505 };
6753 defer f.close();6506 const new_source = source: {
67546507 var f = fs.cwd().openFile(new_source_path, .{}) catch |err|
6755 const stat = try f.stat();6508 fatal("unable to open new source file '{s}': {s}", .{ new_source_path, @errorName(err) });
67566509 defer f.close();
6757 if (stat.size > std.zig.max_src_size)6510 break :source std.zig.readSourceFileToEndAlloc(arena, f, std.zig.max_src_size) catch |err|
6758 return error.FileTooBig;6511 fatal("unable to read new source file '{s}': {s}", .{ new_source_path, @errorName(err) });
6759
6760 var file: Zcu.File = .{
6761 .status = .never_loaded,
6762 .sub_file_path = old_source_file,
6763 .stat = .{
6764 .size = stat.size,
6765 .inode = stat.inode,
6766 .mtime = stat.mtime,
6767 },
6768 .source = null,
6769 .tree = null,
6770 .zir = null,
6771 .zoir = null,
6772 .mod = undefined,
6773 };6512 };
67746513
6775 file.mod = try Package.Module.createLimited(arena, .{6514 const old_tree = try Ast.parse(arena, old_source, .zig);
6776 .root = Path.cwd(),6515 const old_zir = try AstGen.generate(arena, old_tree);
6777 .root_src_path = file.sub_file_path,
6778 .fully_qualified_name = "root",
6779 });
6780
6781 const source = try arena.allocSentinel(u8, @as(usize, @intCast(stat.size)), 0);
6782 const amt = try f.readAll(source);
6783 if (amt != stat.size)
6784 return error.UnexpectedEndOfFile;
6785 file.source = source;
6786
6787 file.tree = try Ast.parse(gpa, file.source.?, .zig);
6788 defer file.tree.?.deinit(gpa);
6789
6790 file.zir = try AstGen.generate(gpa, file.tree.?);
6791 defer file.zir.?.deinit(gpa);
67926516
6793 if (file.zir.?.loweringFailed()) {6517 if (old_zir.loweringFailed()) {
6794 var wip_errors: std.zig.ErrorBundle.Wip = undefined;6518 var wip_errors: std.zig.ErrorBundle.Wip = undefined;
6795 try wip_errors.init(gpa);6519 try wip_errors.init(arena);
6796 defer wip_errors.deinit();6520 try wip_errors.addZirErrorMessages(old_zir, old_tree, old_source, old_source_path);
6797 try Compilation.addZirErrorMessages(&wip_errors, &file);
6798 var error_bundle = try wip_errors.toOwnedBundle("");6521 var error_bundle = try wip_errors.toOwnedBundle("");
6799 defer error_bundle.deinit(gpa);
6800 error_bundle.renderToStdErr(color.renderOptions());6522 error_bundle.renderToStdErr(color.renderOptions());
6801 process.exit(1);6523 process.exit(1);
6802 }6524 }
68036525
6804 var new_f = fs.cwd().openFile(new_source_file, .{}) catch |err| {6526 const new_tree = try Ast.parse(arena, new_source, .zig);
6805 fatal("unable to open new source file for comparison '{s}': {s}", .{ new_source_file, @errorName(err) });6527 const new_zir = try AstGen.generate(arena, new_tree);
6806 };
6807 defer new_f.close();
6808
6809 const new_stat = try new_f.stat();
6810
6811 if (new_stat.size > std.zig.max_src_size)
6812 return error.FileTooBig;
6813
6814 const new_source = try arena.allocSentinel(u8, @as(usize, @intCast(new_stat.size)), 0);
6815 const new_amt = try new_f.readAll(new_source);
6816 if (new_amt != new_stat.size)
6817 return error.UnexpectedEndOfFile;
68186528
6819 var new_tree = try Ast.parse(gpa, new_source, .zig);6529 if (new_zir.loweringFailed()) {
6820 defer new_tree.deinit(gpa);
6821
6822 var old_zir = file.zir.?;
6823 defer old_zir.deinit(gpa);
6824 file.zir = null;
6825 file.zir = try AstGen.generate(gpa, new_tree);
6826
6827 if (file.zir.?.loweringFailed()) {
6828 var wip_errors: std.zig.ErrorBundle.Wip = undefined;6530 var wip_errors: std.zig.ErrorBundle.Wip = undefined;
6829 try wip_errors.init(gpa);6531 try wip_errors.init(arena);
6830 defer wip_errors.deinit();6532 try wip_errors.addZirErrorMessages(new_zir, new_tree, new_source, new_source_path);
6831 try Compilation.addZirErrorMessages(&wip_errors, &file);
6832 var error_bundle = try wip_errors.toOwnedBundle("");6533 var error_bundle = try wip_errors.toOwnedBundle("");
6833 defer error_bundle.deinit(gpa);
6834 error_bundle.renderToStdErr(color.renderOptions());6534 error_bundle.renderToStdErr(color.renderOptions());
6835 process.exit(1);6535 process.exit(1);
6836 }6536 }
68376537
6838 var inst_map: std.AutoHashMapUnmanaged(Zir.Inst.Index, Zir.Inst.Index) = .empty;6538 var inst_map: std.AutoHashMapUnmanaged(Zir.Inst.Index, Zir.Inst.Index) = .empty;
6839 defer inst_map.deinit(gpa);6539 try Zcu.mapOldZirToNew(arena, old_zir, new_zir, &inst_map);
6840
6841 try Zcu.mapOldZirToNew(gpa, old_zir, file.zir.?, &inst_map);
68426540
6843 var bw = io.bufferedWriter(io.getStdOut().writer());6541 var bw = io.bufferedWriter(io.getStdOut().writer());
6844 const stdout = bw.writer();6542 const stdout = bw.writer();
...@@ -7315,7 +7013,7 @@ fn cmdFetch(...@@ -7315,7 +7013,7 @@ fn cmdFetch(
7315 },7013 },
7316 };7014 };
73177015
7318 const cwd_path = try process.getCwdAlloc(arena);7016 const cwd_path = try introspect.getResolvedCwd(arena);
73197017
7320 var build_root = try findBuildRoot(arena, .{7018 var build_root = try findBuildRoot(arena, .{
7321 .cwd_path = cwd_path,7019 .cwd_path = cwd_path,
...@@ -7447,9 +7145,7 @@ fn cmdFetch(...@@ -7447,9 +7145,7 @@ fn cmdFetch(
7447fn createEmptyDependenciesModule(7145fn createEmptyDependenciesModule(
7448 arena: Allocator,7146 arena: Allocator,
7449 main_mod: *Package.Module,7147 main_mod: *Package.Module,
7450 global_cache_directory: Cache.Directory,7148 dirs: Compilation.Directories,
7451 local_cache_directory: Cache.Directory,
7452 builtin_mod: *Package.Module,
7453 global_options: Compilation.Config,7149 global_options: Compilation.Config,
7454) !void {7150) !void {
7455 var source = std.ArrayList(u8).init(arena);7151 var source = std.ArrayList(u8).init(arena);
...@@ -7458,9 +7154,7 @@ fn createEmptyDependenciesModule(...@@ -7458,9 +7154,7 @@ fn createEmptyDependenciesModule(
7458 arena,7154 arena,
7459 source.items,7155 source.items,
7460 main_mod,7156 main_mod,
7461 global_cache_directory,7157 dirs,
7462 local_cache_directory,
7463 builtin_mod,
7464 global_options,7158 global_options,
7465 );7159 );
7466}7160}
...@@ -7471,9 +7165,7 @@ fn createDependenciesModule(...@@ -7471,9 +7165,7 @@ fn createDependenciesModule(
7471 arena: Allocator,7165 arena: Allocator,
7472 source: []const u8,7166 source: []const u8,
7473 main_mod: *Package.Module,7167 main_mod: *Package.Module,
7474 global_cache_directory: Cache.Directory,7168 dirs: Compilation.Directories,
7475 local_cache_directory: Cache.Directory,
7476 builtin_mod: *Package.Module,
7477 global_options: Compilation.Config,7169 global_options: Compilation.Config,
7478) !*Package.Module {7170) !*Package.Module {
7479 // Atomically create the file in a directory named after the hash of its contents.7171 // Atomically create the file in a directory named after the hash of its contents.
...@@ -7481,7 +7173,7 @@ fn createDependenciesModule(...@@ -7481,7 +7173,7 @@ fn createDependenciesModule(
7481 const rand_int = std.crypto.random.int(u64);7173 const rand_int = std.crypto.random.int(u64);
7482 const tmp_dir_sub_path = "tmp" ++ fs.path.sep_str ++ std.fmt.hex(rand_int);7174 const tmp_dir_sub_path = "tmp" ++ fs.path.sep_str ++ std.fmt.hex(rand_int);
7483 {7175 {
7484 var tmp_dir = try local_cache_directory.handle.makeOpenPath(tmp_dir_sub_path, .{});7176 var tmp_dir = try dirs.local_cache.handle.makeOpenPath(tmp_dir_sub_path, .{});
7485 defer tmp_dir.close();7177 defer tmp_dir.close();
7486 try tmp_dir.writeFile(.{ .sub_path = basename, .data = source });7178 try tmp_dir.writeFile(.{ .sub_path = basename, .data = source });
7487 }7179 }
...@@ -7493,18 +7185,14 @@ fn createDependenciesModule(...@@ -7493,18 +7185,14 @@ fn createDependenciesModule(
74937185
7494 const o_dir_sub_path = try arena.dupe(u8, "o" ++ fs.path.sep_str ++ hex_digest);7186 const o_dir_sub_path = try arena.dupe(u8, "o" ++ fs.path.sep_str ++ hex_digest);
7495 try Package.Fetch.renameTmpIntoCache(7187 try Package.Fetch.renameTmpIntoCache(
7496 local_cache_directory.handle,7188 dirs.local_cache.handle,
7497 tmp_dir_sub_path,7189 tmp_dir_sub_path,
7498 o_dir_sub_path,7190 o_dir_sub_path,
7499 );7191 );
75007192
7501 const deps_mod = try Package.Module.create(arena, .{7193 const deps_mod = try Package.Module.create(arena, .{
7502 .global_cache_directory = global_cache_directory,
7503 .paths = .{7194 .paths = .{
7504 .root = .{7195 .root = try .fromRoot(arena, dirs, .local_cache, o_dir_sub_path),
7505 .root_dir = local_cache_directory,
7506 .sub_path = o_dir_sub_path,
7507 },
7508 .root_src_path = basename,7196 .root_src_path = basename,
7509 },7197 },
7510 .fully_qualified_name = "root.@dependencies",7198 .fully_qualified_name = "root.@dependencies",
...@@ -7512,8 +7200,6 @@ fn createDependenciesModule(...@@ -7512,8 +7200,6 @@ fn createDependenciesModule(
7512 .cc_argv = &.{},7200 .cc_argv = &.{},
7513 .inherited = .{},7201 .inherited = .{},
7514 .global = global_options,7202 .global = global_options,
7515 .builtin_mod = builtin_mod,
7516 .builtin_modules = null, // `builtin_mod` is specified
7517 });7203 });
7518 try main_mod.deps.put(arena, "@dependencies", deps_mod);7204 try main_mod.deps.put(arena, "@dependencies", deps_mod);
7519 return deps_mod;7205 return deps_mod;
...@@ -7536,7 +7222,7 @@ const FindBuildRootOptions = struct {...@@ -7536,7 +7222,7 @@ const FindBuildRootOptions = struct {
7536};7222};
75377223
7538fn findBuildRoot(arena: Allocator, options: FindBuildRootOptions) !BuildRoot {7224fn findBuildRoot(arena: Allocator, options: FindBuildRootOptions) !BuildRoot {
7539 const cwd_path = options.cwd_path orelse try process.getCwdAlloc(arena);7225 const cwd_path = options.cwd_path orelse try introspect.getResolvedCwd(arena);
7540 const build_zig_basename = if (options.build_file) |bf|7226 const build_zig_basename = if (options.build_file) |bf|
7541 fs.path.basename(bf)7227 fs.path.basename(bf)
7542 else7228 else
...@@ -7723,10 +7409,13 @@ const Templates = struct {...@@ -7723,10 +7409,13 @@ const Templates = struct {
7723};7409};
77247410
7725fn findTemplates(gpa: Allocator, arena: Allocator) Templates {7411fn findTemplates(gpa: Allocator, arena: Allocator) Templates {
7726 const self_exe_path = introspect.findZigExePath(arena) catch |err| {7412 const cwd_path = introspect.getResolvedCwd(arena) catch |err| {
7413 fatal("unable to get cwd: {s}", .{@errorName(err)});
7414 };
7415 const self_exe_path = fs.selfExePathAlloc(arena) catch |err| {
7727 fatal("unable to find self exe path: {s}", .{@errorName(err)});7416 fatal("unable to find self exe path: {s}", .{@errorName(err)});
7728 };7417 };
7729 var zig_lib_directory = introspect.findZigLibDirFromSelfExe(arena, self_exe_path) catch |err| {7418 var zig_lib_directory = introspect.findZigLibDirFromSelfExe(arena, cwd_path, self_exe_path) catch |err| {
7730 fatal("unable to find zig installation directory '{s}': {s}", .{ self_exe_path, @errorName(err) });7419 fatal("unable to find zig installation directory '{s}': {s}", .{ self_exe_path, @errorName(err) });
7731 };7420 };
77327421
...@@ -7783,8 +7472,8 @@ fn handleModArg(...@@ -7783,8 +7472,8 @@ fn handleModArg(
7783 const gop = try create_module.modules.getOrPut(arena, mod_name);7472 const gop = try create_module.modules.getOrPut(arena, mod_name);
77847473
7785 if (gop.found_existing) {7474 if (gop.found_existing) {
7786 fatal("unable to add module '{s}': already exists as '{s}'", .{7475 fatal("unable to add module '{s}': already exists as '{s}{c}{s}'", .{
7787 mod_name, gop.value_ptr.paths.root_src_path,7476 mod_name, gop.value_ptr.root_path, fs.path.sep, gop.value_ptr.root_src_path,
7788 });7477 });
7789 }7478 }
77907479
...@@ -7811,24 +7500,14 @@ fn handleModArg(...@@ -7811,24 +7500,14 @@ fn handleModArg(
7811 if (mod_opts.error_tracing == true)7500 if (mod_opts.error_tracing == true)
7812 create_module.opts.any_error_tracing = true;7501 create_module.opts.any_error_tracing = true;
78137502
7503 const root_path: []const u8, const root_src_path: []const u8 = if (opt_root_src_orig) |path| root: {
7504 create_module.opts.have_zcu = true;
7505 break :root .{ fs.path.dirname(path) orelse ".", fs.path.basename(path) };
7506 } else .{ ".", "" };
7507
7814 gop.value_ptr.* = .{7508 gop.value_ptr.* = .{
7815 .paths = p: {7509 .root_path = root_path,
7816 if (opt_root_src_orig) |root_src_orig| {7510 .root_src_path = root_src_path,
7817 create_module.opts.have_zcu = true;
7818 const root_src = try introspect.resolvePath(arena, root_src_orig);
7819 break :p .{
7820 .root = .{
7821 .root_dir = Cache.Directory.cwd(),
7822 .sub_path = fs.path.dirname(root_src) orelse "",
7823 },
7824 .root_src_path = fs.path.basename(root_src),
7825 };
7826 }
7827 break :p .{
7828 .root = .{ .root_dir = Cache.Directory.cwd() },
7829 .root_src_path = "",
7830 };
7831 },
7832 .cc_argv = try cc_argv.toOwnedSlice(arena),7511 .cc_argv = try cc_argv.toOwnedSlice(arena),
7833 .inherited = mod_opts.*,7512 .inherited = mod_opts.*,
7834 .target_arch_os_abi = target_arch_os_abi.*,7513 .target_arch_os_abi = target_arch_os_abi.*,
src/print_env.zig+4-3
...@@ -2,13 +2,14 @@ const std = @import("std");...@@ -2,13 +2,14 @@ const std = @import("std");
2const build_options = @import("build_options");2const build_options = @import("build_options");
3const introspect = @import("introspect.zig");3const introspect = @import("introspect.zig");
4const Allocator = std.mem.Allocator;4const Allocator = std.mem.Allocator;
5const fatal = @import("main.zig").fatal;5const fatal = std.process.fatal;
66
7pub fn cmdEnv(arena: Allocator, args: []const []const u8, stdout: std.fs.File.Writer) !void {7pub fn cmdEnv(arena: Allocator, args: []const []const u8, stdout: std.fs.File.Writer) !void {
8 _ = args;8 _ = args;
9 const self_exe_path = try introspect.findZigExePath(arena);9 const cwd_path = try introspect.getResolvedCwd(arena);
10 const self_exe_path = try std.fs.selfExePathAlloc(arena);
1011
11 var zig_lib_directory = introspect.findZigLibDirFromSelfExe(arena, self_exe_path) catch |err| {12 var zig_lib_directory = introspect.findZigLibDirFromSelfExe(arena, cwd_path, self_exe_path) catch |err| {
12 fatal("unable to find zig installation directory: {s}\n", .{@errorName(err)});13 fatal("unable to find zig installation directory: {s}\n", .{@errorName(err)});
13 };14 };
14 defer zig_lib_directory.handle.close();15 defer zig_lib_directory.handle.close();
src/print_targets.zig+1-1
...@@ -3,13 +3,13 @@ const fs = std.fs;...@@ -3,13 +3,13 @@ const fs = std.fs;
3const io = std.io;3const io = std.io;
4const mem = std.mem;4const mem = std.mem;
5const meta = std.meta;5const meta = std.meta;
6const fatal = std.process.fatal;
6const Allocator = std.mem.Allocator;7const Allocator = std.mem.Allocator;
7const Target = std.Target;8const Target = std.Target;
8const target = @import("target.zig");9const target = @import("target.zig");
9const assert = std.debug.assert;10const assert = std.debug.assert;
10const glibc = @import("libs/glibc.zig");11const glibc = @import("libs/glibc.zig");
11const introspect = @import("introspect.zig");12const introspect = @import("introspect.zig");
12const fatal = @import("main.zig").fatal;
1313
14pub fn cmdTargets(14pub fn cmdTargets(
15 allocator: Allocator,15 allocator: Allocator,
src/print_zir.zig+14-13
...@@ -12,7 +12,8 @@ const LazySrcLoc = Zcu.LazySrcLoc;...@@ -12,7 +12,8 @@ const LazySrcLoc = Zcu.LazySrcLoc;
12/// Write human-readable, debug formatted ZIR code to a file.12/// Write human-readable, debug formatted ZIR code to a file.
13pub fn renderAsTextToFile(13pub fn renderAsTextToFile(
14 gpa: Allocator,14 gpa: Allocator,
15 scope_file: *Zcu.File,15 tree: ?Ast,
16 zir: Zir,
16 fs_file: std.fs.File,17 fs_file: std.fs.File,
17) !void {18) !void {
18 var arena = std.heap.ArenaAllocator.init(gpa);19 var arena = std.heap.ArenaAllocator.init(gpa);
...@@ -21,8 +22,8 @@ pub fn renderAsTextToFile(...@@ -21,8 +22,8 @@ pub fn renderAsTextToFile(
21 var writer: Writer = .{22 var writer: Writer = .{
22 .gpa = gpa,23 .gpa = gpa,
23 .arena = arena.allocator(),24 .arena = arena.allocator(),
24 .file = scope_file,25 .tree = tree,
25 .code = scope_file.zir.?,26 .code = zir,
26 .indent = 0,27 .indent = 0,
27 .parent_decl_node = .root,28 .parent_decl_node = .root,
28 .recurse_decls = true,29 .recurse_decls = true,
...@@ -36,18 +37,18 @@ pub fn renderAsTextToFile(...@@ -36,18 +37,18 @@ pub fn renderAsTextToFile(
36 try stream.print("%{d} ", .{@intFromEnum(main_struct_inst)});37 try stream.print("%{d} ", .{@intFromEnum(main_struct_inst)});
37 try writer.writeInstToStream(stream, main_struct_inst);38 try writer.writeInstToStream(stream, main_struct_inst);
38 try stream.writeAll("\n");39 try stream.writeAll("\n");
39 const imports_index = scope_file.zir.?.extra[@intFromEnum(Zir.ExtraIndex.imports)];40 const imports_index = zir.extra[@intFromEnum(Zir.ExtraIndex.imports)];
40 if (imports_index != 0) {41 if (imports_index != 0) {
41 try stream.writeAll("Imports:\n");42 try stream.writeAll("Imports:\n");
4243
43 const extra = scope_file.zir.?.extraData(Zir.Inst.Imports, imports_index);44 const extra = zir.extraData(Zir.Inst.Imports, imports_index);
44 var extra_index = extra.end;45 var extra_index = extra.end;
4546
46 for (0..extra.data.imports_len) |_| {47 for (0..extra.data.imports_len) |_| {
47 const item = scope_file.zir.?.extraData(Zir.Inst.Imports.Item, extra_index);48 const item = zir.extraData(Zir.Inst.Imports.Item, extra_index);
48 extra_index = item.end;49 extra_index = item.end;
4950
50 const import_path = scope_file.zir.?.nullTerminatedString(item.data.name);51 const import_path = zir.nullTerminatedString(item.data.name);
51 try stream.print(" @import(\"{}\") ", .{52 try stream.print(" @import(\"{}\") ", .{
52 std.zig.fmtEscapes(import_path),53 std.zig.fmtEscapes(import_path),
53 });54 });
...@@ -74,7 +75,7 @@ pub fn renderInstructionContext(...@@ -74,7 +75,7 @@ pub fn renderInstructionContext(
74 var writer: Writer = .{75 var writer: Writer = .{
75 .gpa = gpa,76 .gpa = gpa,
76 .arena = arena.allocator(),77 .arena = arena.allocator(),
77 .file = scope_file,78 .tree = scope_file.tree,
78 .code = scope_file.zir.?,79 .code = scope_file.zir.?,
79 .indent = if (indent < 2) 2 else indent,80 .indent = if (indent < 2) 2 else indent,
80 .parent_decl_node = parent_decl_node,81 .parent_decl_node = parent_decl_node,
...@@ -106,7 +107,7 @@ pub fn renderSingleInstruction(...@@ -106,7 +107,7 @@ pub fn renderSingleInstruction(
106 var writer: Writer = .{107 var writer: Writer = .{
107 .gpa = gpa,108 .gpa = gpa,
108 .arena = arena.allocator(),109 .arena = arena.allocator(),
109 .file = scope_file,110 .tree = scope_file.tree,
110 .code = scope_file.zir.?,111 .code = scope_file.zir.?,
111 .indent = indent,112 .indent = indent,
112 .parent_decl_node = parent_decl_node,113 .parent_decl_node = parent_decl_node,
...@@ -121,7 +122,7 @@ pub fn renderSingleInstruction(...@@ -121,7 +122,7 @@ pub fn renderSingleInstruction(
121const Writer = struct {122const Writer = struct {
122 gpa: Allocator,123 gpa: Allocator,
123 arena: Allocator,124 arena: Allocator,
124 file: *Zcu.File,125 tree: ?Ast,
125 code: Zir,126 code: Zir,
126 indent: u32,127 indent: u32,
127 parent_decl_node: Ast.Node.Index,128 parent_decl_node: Ast.Node.Index,
...@@ -2761,7 +2762,7 @@ const Writer = struct {...@@ -2761,7 +2762,7 @@ const Writer = struct {
2761 }2762 }
27622763
2763 fn writeSrcNode(self: *Writer, stream: anytype, src_node: Ast.Node.Offset) !void {2764 fn writeSrcNode(self: *Writer, stream: anytype, src_node: Ast.Node.Offset) !void {
2764 const tree = self.file.tree orelse return;2765 const tree = self.tree orelse return;
2765 const abs_node = src_node.toAbsolute(self.parent_decl_node);2766 const abs_node = src_node.toAbsolute(self.parent_decl_node);
2766 const src_span = tree.nodeToSpan(abs_node);2767 const src_span = tree.nodeToSpan(abs_node);
2767 const start = self.line_col_cursor.find(tree.source, src_span.start);2768 const start = self.line_col_cursor.find(tree.source, src_span.start);
...@@ -2773,7 +2774,7 @@ const Writer = struct {...@@ -2773,7 +2774,7 @@ const Writer = struct {
2773 }2774 }
27742775
2775 fn writeSrcTok(self: *Writer, stream: anytype, src_tok: Ast.TokenOffset) !void {2776 fn writeSrcTok(self: *Writer, stream: anytype, src_tok: Ast.TokenOffset) !void {
2776 const tree = self.file.tree orelse return;2777 const tree = self.tree orelse return;
2777 const abs_tok = src_tok.toAbsolute(tree.firstToken(self.parent_decl_node));2778 const abs_tok = src_tok.toAbsolute(tree.firstToken(self.parent_decl_node));
2778 const span_start = tree.tokenStart(abs_tok);2779 const span_start = tree.tokenStart(abs_tok);
2779 const span_end = span_start + @as(u32, @intCast(tree.tokenSlice(abs_tok).len));2780 const span_end = span_start + @as(u32, @intCast(tree.tokenSlice(abs_tok).len));
...@@ -2786,7 +2787,7 @@ const Writer = struct {...@@ -2786,7 +2787,7 @@ const Writer = struct {
2786 }2787 }
27872788
2788 fn writeSrcTokAbs(self: *Writer, stream: anytype, src_tok: Ast.TokenIndex) !void {2789 fn writeSrcTokAbs(self: *Writer, stream: anytype, src_tok: Ast.TokenIndex) !void {
2789 const tree = self.file.tree orelse return;2790 const tree = self.tree orelse return;
2790 const span_start = tree.tokenStart(src_tok);2791 const span_start = tree.tokenStart(src_tok);
2791 const span_end = span_start + @as(u32, @intCast(tree.tokenSlice(src_tok).len));2792 const span_end = span_start + @as(u32, @intCast(tree.tokenSlice(src_tok).len));
2792 const start = self.line_col_cursor.find(tree.source, span_start);2793 const start = self.line_col_cursor.find(tree.source, span_start);
test/cases/compile_errors/bad_import.zig+2-3
...@@ -3,7 +3,6 @@ const bogus = @import(...@@ -3,7 +3,6 @@ const bogus = @import(
3);3);
44
5// error5// error
6// backend=stage2
7// target=native
8//6//
9// bogus-does-not-exist.zig': FileNotFound7// bogus-does-not-exist.zig:1:1: error: unable to load 'bogus-does-not-exist.zig': FileNotFound
8// :2:5: note: file imported here
test/cases/compile_errors/import_of_missing_module.zig created+8
...@@ -0,0 +1,8 @@
1const foo = @import("foo");
2comptime {
3 _ = foo;
4}
5
6// error
7//
8// :1:21: error: no module named 'foo' available within module 'root'
test/cases/compile_errors/import_of_missing_package.zig deleted-10
...@@ -1,10 +0,0 @@
1const foo = @import("foo");
2comptime {
3 _ = foo;
4}
5
6// error
7// backend=stage2
8// target=native
9//
10// :1:21: error: no module named 'foo' available within module root
test/cases/compile_errors/import_outside_module_path.zig created+7
...@@ -0,0 +1,7 @@
1comptime {
2 _ = @import("../a.zig");
3}
4
5// error
6//
7// :2:17: error: import of file outside module path
test/cases/compile_errors/import_outside_package.zig deleted-8
...@@ -1,8 +0,0 @@
1export fn a() usize {
2 return @import("../../above.zig").len;
3}
4
5// error
6// target=native
7//
8// :2:20: error: import of file outside module path: '../../above.zig'
test/cases/compile_errors/import_outside_package_path.zig deleted-9
...@@ -1,9 +0,0 @@
1comptime {
2 _ = @import("../a.zig");
3}
4
5// error
6// backend=stage2
7// target=native
8//
9// :2:17: error: import of file outside module path: '../a.zig'
test/compile_errors.zig+4-3
...@@ -126,9 +126,10 @@ pub fn addCases(ctx: *Cases, b: *std.Build) !void {...@@ -126,9 +126,10 @@ pub fn addCases(ctx: *Cases, b: *std.Build) !void {
126 \\ _ = @import("foo.zig");126 \\ _ = @import("foo.zig");
127 \\}127 \\}
128 , &[_][]const u8{128 , &[_][]const u8{
129 ":1:1: error: file exists in multiple modules",129 ":1:1: error: file exists in modules 'foo' and 'root'",
130 ":1:1: note: root of module foo",130 ":1:1: note: files must belong to only one module",
131 ":3:17: note: imported from module root",131 ":1:1: note: file is the root of module 'foo'",
132 ":3:17: note: file is imported here by the root of module 'root'",
132 });133 });
133 case.addSourceFile("foo.zig",134 case.addSourceFile("foo.zig",
134 \\const dummy = 0;135 \\const dummy = 0;
test/incremental/bad_import created+35
...@@ -0,0 +1,35 @@
1#target=x86_64-linux-selfhosted
2#target=x86_64-linux-cbe
3#target=x86_64-windows-cbe
4#target=wasm32-wasi-selfhosted
5
6#update=initial version
7#file=main.zig
8pub fn main() !void {
9 _ = @import("foo.zig");
10 try std.io.getStdOut().writeAll("success\n");
11}
12const std = @import("std");
13#file=foo.zig
14comptime {
15 _ = @import("bad.zig");
16}
17#expect_error=bad.zig:1:1: error: unable to load 'bad.zig': FileNotFound
18#expect_error=foo.zig:2:17: note: file imported here
19
20#update=change bad import
21#file=foo.zig
22comptime {
23 _ = @import("this_is/not_real.zig");
24}
25#expect_error=this_is/not_real.zig:1:1: error: unable to load 'not_real.zig': FileNotFound
26#expect_error=foo.zig:2:17: note: file imported here
27
28#update=remove import of 'foo.zig'
29#file=main.zig
30pub fn main() !void {
31 //_ = @import("foo.zig");
32 try std.io.getStdOut().writeAll("success\n");
33}
34const std = @import("std");
35#expect_stdout="success\n"
test/incremental/change_module created+65
...@@ -0,0 +1,65 @@
1#target=x86_64-linux-selfhosted
2#target=x86_64-linux-cbe
3#target=x86_64-windows-cbe
4#target=wasm32-wasi-selfhosted
5#module=foo=foo.zig
6
7#update=initial version
8#file=main.zig
9pub fn main() void {
10 _ = @import("foo");
11 //_ = @import("other.zig");
12}
13#file=foo.zig
14comptime {
15 _ = @import("other.zig");
16}
17#file=other.zig
18fn f() void {
19 @compileLog(@src().module);
20}
21comptime {
22 f();
23}
24#expect_error=other.zig:2:5: error: found compile log statement
25#expect_compile_log=@as([:0]const u8, "foo"[0..3])
26
27#update=change module of other.zig
28#file=main.zig
29pub fn main() void {
30 _ = @import("foo");
31 _ = @import("other.zig");
32}
33#file=foo.zig
34comptime {
35 //_ = @import("other.zig");
36}
37#expect_error=other.zig:2:5: error: found compile log statement
38#expect_compile_log=@as([:0]const u8, "root"[0..4])
39
40#update=put other.zig in both modules
41#file=main.zig
42pub fn main() void {
43 _ = @import("foo");
44 _ = @import("other.zig");
45}
46#file=foo.zig
47comptime {
48 _ = @import("other.zig");
49}
50#expect_error=foo.zig:1:1: error: file exists in modules 'root' and 'foo'
51#expect_error=foo.zig:1:1: note: files must belong to only one module
52#expect_error=main.zig:3:17: note: file is imported here by the root of module 'root'
53#expect_error=foo.zig:2:17: note: file is imported here by the root of module 'foo'
54
55#update=put other.zig in no modules
56#file=main.zig
57pub fn main() void {
58 _ = @import("foo");
59 //_ = @import("other.zig");
60}
61#file=foo.zig
62comptime {
63 //_ = @import("other.zig");
64}
65#expect_stdout=""
test/incremental/change_zon_file+4-2
...@@ -20,7 +20,8 @@ pub fn main() !void {...@@ -20,7 +20,8 @@ pub fn main() !void {
2020
21#update=delete file21#update=delete file
22#rm_file=message.zon22#rm_file=message.zon
23#expect_error=message.zon:1:1: error: unable to load './message.zon': FileNotFound23#expect_error=message.zon:1:1: error: unable to load 'message.zon': FileNotFound
24#expect_error=main.zig:2:37: note: file imported here
2425
25#update=remove reference to ZON file26#update=remove reference to ZON file
26#file=main.zig27#file=main.zig
...@@ -29,7 +30,8 @@ const message: []const u8 = @import("message.zon");...@@ -29,7 +30,8 @@ const message: []const u8 = @import("message.zon");
29pub fn main() !void {30pub fn main() !void {
30 try std.io.getStdOut().writeAll("a hardcoded string\n");31 try std.io.getStdOut().writeAll("a hardcoded string\n");
31}32}
32#expect_error=message.zon:1:1: error: unable to load './message.zon': FileNotFound33#expect_error=message.zon:1:1: error: unable to load 'message.zon': FileNotFound
34#expect_error=main.zig:2:37: note: file imported here
3335
34#update=recreate ZON file36#update=recreate ZON file
35#file=message.zon37#file=message.zon
test/standalone/dep_recursive/test.zig-1
...@@ -1,5 +1,4 @@...@@ -1,5 +1,4 @@
1const foo = @import("foo");1const foo = @import("foo");
2const shared = @import("shared");
3const assert = @import("std").debug.assert;2const assert = @import("std").debug.assert;
43
5pub fn main() void {4pub fn main() void {
tools/incr-check.zig+37-7
...@@ -106,7 +106,6 @@ pub fn main() !void {...@@ -106,7 +106,6 @@ pub fn main() !void {
106 try child_args.appendSlice(arena, &.{106 try child_args.appendSlice(arena, &.{
107 resolved_zig_exe,107 resolved_zig_exe,
108 "build-exe",108 "build-exe",
109 case.root_source_file,
110 "-fincremental",109 "-fincremental",
111 "-fno-ubsan-rt",110 "-fno-ubsan-rt",
112 "-target",111 "-target",
...@@ -135,6 +134,13 @@ pub fn main() !void {...@@ -135,6 +134,13 @@ pub fn main() !void {
135 if (debug_link) {134 if (debug_link) {
136 try child_args.appendSlice(arena, &.{ "--debug-log", "link", "--debug-log", "link_state", "--debug-log", "link_relocs" });135 try child_args.appendSlice(arena, &.{ "--debug-log", "link", "--debug-log", "link_state", "--debug-log", "link_relocs" });
137 }136 }
137 for (case.modules) |mod| {
138 try child_args.appendSlice(arena, &.{ "--dep", mod.name });
139 }
140 try child_args.append(arena, try std.fmt.allocPrint(arena, "-Mroot={s}", .{case.root_source_file}));
141 for (case.modules) |mod| {
142 try child_args.append(arena, try std.fmt.allocPrint(arena, "-M{s}={s}", .{ mod.name, mod.file }));
143 }
138144
139 const zig_prog_node = target_prog_node.start("zig build-exe", 0);145 const zig_prog_node = target_prog_node.start("zig build-exe", 0);
140 defer zig_prog_node.end();146 defer zig_prog_node.end();
...@@ -308,9 +314,8 @@ const Eval = struct {...@@ -308,9 +314,8 @@ const Eval = struct {
308 const digest = body[@sizeOf(EbpHdr)..][0..Cache.bin_digest_len];314 const digest = body[@sizeOf(EbpHdr)..][0..Cache.bin_digest_len];
309 const result_dir = ".local-cache" ++ std.fs.path.sep_str ++ "o" ++ std.fs.path.sep_str ++ Cache.binToHex(digest.*);315 const result_dir = ".local-cache" ++ std.fs.path.sep_str ++ "o" ++ std.fs.path.sep_str ++ Cache.binToHex(digest.*);
310316
311 const name = std.fs.path.stem(std.fs.path.basename(eval.case.root_source_file));
312 const bin_name = try std.zig.binNameAlloc(arena, .{317 const bin_name = try std.zig.binNameAlloc(arena, .{
313 .root_name = name,318 .root_name = "root", // corresponds to the module name "root"
314 .target = eval.target.resolved,319 .target = eval.target.resolved,
315 .output_mode = .Exe,320 .output_mode = .Exe,
316 });321 });
...@@ -359,7 +364,7 @@ const Eval = struct {...@@ -359,7 +364,7 @@ const Eval = struct {
359 error_bundle.renderToStdErr(color.renderOptions());364 error_bundle.renderToStdErr(color.renderOptions());
360 eval.fatal("update '{s}': more errors than expected", .{update.name});365 eval.fatal("update '{s}': more errors than expected", .{update.name});
361 }366 }
362 eval.checkOneError(update, error_bundle, expected.errors[expected_idx], false, err_idx);367 try eval.checkOneError(update, error_bundle, expected.errors[expected_idx], false, err_idx);
363 expected_idx += 1;368 expected_idx += 1;
364369
365 for (error_bundle.getNotes(err_idx)) |note_idx| {370 for (error_bundle.getNotes(err_idx)) |note_idx| {
...@@ -368,7 +373,7 @@ const Eval = struct {...@@ -368,7 +373,7 @@ const Eval = struct {
368 error_bundle.renderToStdErr(color.renderOptions());373 error_bundle.renderToStdErr(color.renderOptions());
369 eval.fatal("update '{s}': more error notes than expected", .{update.name});374 eval.fatal("update '{s}': more error notes than expected", .{update.name});
370 }375 }
371 eval.checkOneError(update, error_bundle, expected.errors[expected_idx], true, note_idx);376 try eval.checkOneError(update, error_bundle, expected.errors[expected_idx], true, note_idx);
372 expected_idx += 1;377 expected_idx += 1;
373 }378 }
374 }379 }
...@@ -387,13 +392,21 @@ const Eval = struct {...@@ -387,13 +392,21 @@ const Eval = struct {
387 expected: Case.ExpectedError,392 expected: Case.ExpectedError,
388 is_note: bool,393 is_note: bool,
389 err_idx: std.zig.ErrorBundle.MessageIndex,394 err_idx: std.zig.ErrorBundle.MessageIndex,
390 ) void {395 ) Allocator.Error!void {
391 const err = eb.getErrorMessage(err_idx);396 const err = eb.getErrorMessage(err_idx);
392 if (err.src_loc == .none) @panic("TODO error message with no source location");397 if (err.src_loc == .none) @panic("TODO error message with no source location");
393 if (err.count != 1) @panic("TODO error message with count>1");398 if (err.count != 1) @panic("TODO error message with count>1");
394 const msg = eb.nullTerminatedString(err.msg);399 const msg = eb.nullTerminatedString(err.msg);
395 const src = eb.getSourceLocation(err.src_loc);400 const src = eb.getSourceLocation(err.src_loc);
396 const filename = eb.nullTerminatedString(src.src_path);401 const raw_filename = eb.nullTerminatedString(src.src_path);
402
403 // We need to replace backslashes for consistency between platforms.
404 const filename = name: {
405 if (std.mem.indexOfScalar(u8, raw_filename, '\\') == null) break :name raw_filename;
406 const copied = try eval.arena.dupe(u8, raw_filename);
407 std.mem.replaceScalar(u8, copied, '\\', '/');
408 break :name copied;
409 };
397410
398 if (expected.is_note != is_note or411 if (expected.is_note != is_note or
399 !std.mem.eql(u8, expected.filename, filename) or412 !std.mem.eql(u8, expected.filename, filename) or
...@@ -605,6 +618,7 @@ const Case = struct {...@@ -605,6 +618,7 @@ const Case = struct {
605 updates: []Update,618 updates: []Update,
606 root_source_file: []const u8,619 root_source_file: []const u8,
607 targets: []const Target,620 targets: []const Target,
621 modules: []const Module,
608622
609 const Target = struct {623 const Target = struct {
610 query: []const u8,624 query: []const u8,
...@@ -626,6 +640,11 @@ const Case = struct {...@@ -626,6 +640,11 @@ const Case = struct {
626 };640 };
627 };641 };
628642
643 const Module = struct {
644 name: []const u8,
645 file: []const u8,
646 };
647
629 const Update = struct {648 const Update = struct {
630 name: []const u8,649 name: []const u8,
631 outcome: Outcome,650 outcome: Outcome,
...@@ -660,6 +679,7 @@ const Case = struct {...@@ -660,6 +679,7 @@ const Case = struct {
660 const fatal = std.process.fatal;679 const fatal = std.process.fatal;
661680
662 var targets: std.ArrayListUnmanaged(Target) = .empty;681 var targets: std.ArrayListUnmanaged(Target) = .empty;
682 var modules: std.ArrayListUnmanaged(Module) = .empty;
663 var updates: std.ArrayListUnmanaged(Update) = .empty;683 var updates: std.ArrayListUnmanaged(Update) = .empty;
664 var changes: std.ArrayListUnmanaged(FullContents) = .empty;684 var changes: std.ArrayListUnmanaged(FullContents) = .empty;
665 var deletes: std.ArrayListUnmanaged([]const u8) = .empty;685 var deletes: std.ArrayListUnmanaged([]const u8) = .empty;
...@@ -698,6 +718,15 @@ const Case = struct {...@@ -698,6 +718,15 @@ const Case = struct {
698 .resolved = resolved,718 .resolved = resolved,
699 .backend = backend,719 .backend = backend,
700 });720 });
721 } else if (std.mem.eql(u8, key, "module")) {
722 const split_idx = std.mem.indexOfScalar(u8, val, '=') orelse
723 fatal("line {d}: module does not include file", .{line_n});
724 const name = val[0..split_idx];
725 const file = val[split_idx + 1 ..];
726 try modules.append(arena, .{
727 .name = name,
728 .file = file,
729 });
701 } else if (std.mem.eql(u8, key, "update")) {730 } else if (std.mem.eql(u8, key, "update")) {
702 if (updates.items.len > 0) {731 if (updates.items.len > 0) {
703 const last_update = &updates.items[updates.items.len - 1];732 const last_update = &updates.items[updates.items.len - 1];
...@@ -811,6 +840,7 @@ const Case = struct {...@@ -811,6 +840,7 @@ const Case = struct {
811 .updates = updates.items,840 .updates = updates.items,
812 .root_source_file = root_source_file orelse fatal("missing root source file", .{}),841 .root_source_file = root_source_file orelse fatal("missing root source file", .{}),
813 .targets = targets.items, // arena so no need for toOwnedSlice842 .targets = targets.items, // arena so no need for toOwnedSlice
843 .modules = modules.items,
814 };844 };
815 }845 }
816};846};