authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2025-05-04 17:02:25+01:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2025-05-18 17:37:02+01:00
log37a9a4e0f16c1df8de3a4add3a9566b24f024a95
tree0fc8f1fc15193e8e3c3ccd5e97408cef7372f394
parentd32829e053af2a0f382d4d692ede85c176c9f803
signaturelock-open Commit is signed but in an unrecognized format.

compiler: refactor `Zcu.File` and path representation

This commit makes some big changes to how we track state for Zig source files. In particular, it changes: * How `File` tracks its path on-disk * How AstGen discovers files * How file-level errors are tracked * How `builtin.zig` files and modules are created The original motivation here was to address incremental compilation bugs with the handling of files, such as #22696. To fix this, a few changes are necessary. Just like declarations may become unreferenced on an incremental update, meaning we suppress analysis errors associated with them, it is also possible for all imports of a file to be removed on an incremental update, in which case file-level errors for that file should be suppressed. As such, after AstGen, the compiler must traverse files (starting from analysis roots) and discover the set of "live files" for this update. Additionally, the compiler's previous handling of retryable file errors was not very good; the source location the error was reported as was based only on the first discovered import of that file. This source location also disappeared on future incremental updates. So, as a part of the file traversal above, we also need to figure out the source locations of imports which errors should be reported against. Another observation I made is that the "file exists in multiple modules" error was not implemented in a particularly good way (I get to say that because I wrote it!). It was subject to races, where the order in which different imports of a file were discovered affects both how errors are printed, and which module the file is arbitrarily assigned, with the latter in turn affecting which other files are considered for import. The thing I realised here is that while the AstGen worker pool is running, we cannot know for sure which module(s) a file is in; we could always discover an import later which changes the answer. So, here's how the AstGen workers have changed. We initially ensure that `zcu.import_table` contains the root files for all modules in this Zcu, even if we don't know any imports for them yet. Then, the AstGen workers do not need to be aware of modules. Instead, they simply ignore module imports, and only spin off more workers when they see a by-path import. During AstGen, we can't use module-root-relative paths, since we don't know which modules files are in; but we don't want to unnecessarily use absolute files either, because those are non-portable and can make `error.NameTooLong` more likely. As such, I have introduced a new abstraction, `Compilation.Path`. This type is a way of representing a filesystem path which has a *canonical form*. The path is represented relative to one of a few special directories: the lib directory, the global cache directory, or the local cache directory. As a fallback, we use absolute (or cwd-relative on WASI) paths. This is kind of similar to `std.Build.Cache.Path` with a pre-defined list of possible `std.Build.Cache.Directory`, but has stricter canonicalization rules based on path resolution to make sure deduplicating files works properly. A `Compilation.Path` can be trivially converted to a `std.Build.Cache.Path` from a `Compilation`, but is smaller, has a canonical form, and has a digest which will be consistent across different compiler processes with the same lib and cache directories (important when we serialize incremental compilation state in the future). `Zcu.File` and `Zcu.EmbedFile` both contain a `Compilation.Path`, which is used to access the file on-disk; module-relative sub paths are used quite rarely (`EmbedFile` doesn't even have one now for simplicity). After the AstGen workers all complete, we know that any file which might be imported is definitely in `import_table` and up-to-date. So, we perform a single-threaded graph traversal; similar to what `resolveReferences` plays for `AnalUnit`s, but for files instead. We figure out which files are alive, and which module each file is in. If a file turns out to be in multiple modules, we set a field on `Zcu` to indicate this error. If a file is in a different module to a prior update, we set a flag instructing `updateZirRefs` to invalidate all dependencies on the file. This traversal also discovers "import errors"; these are errors associated with a specific `@import`. With Zig's current design, there is only one possible error here: "import outside of module root". This must be identified during this traversal instead of during AstGen, because it depends on which module the file is in. I tried also representing "module not found" errors in this same way, but it turns out to be much more useful to report those in Sema, because of use cases like optional dependencies where a module import is behind a comptime-known build option. For simplicity, `failed_files` now just maps to `?[]u8`, since the source location is always the whole file. In fact, this allows removing `LazySrcLoc.Offset.entire_file` completely, slightly simplifying some error reporting logic. File-level errors are now directly built in the `std.zig.ErrorBundle.Wip`. If the payload is not `null`, it is the message for a retryable error (i.e. an error loading the source file), and will be reported with a "file imported here" note pointing to the import site discovered during the single-threaded file traversal. The last piece of fallout here is how `Builtin` works. Rather than constructing "builtin" modules when creating `Package.Module`s, they are now constructed on-the-fly by `Zcu`. The map `Zcu.builtin_modules` maps from digests to `*Package.Module`s. These digests are abstract hashes of the `Builtin` value; i.e. all of the options which are placed into "builtin.zig". During the file traversal, we populate `builtin_modules` as needed, so that when we see this imports in Sema, we just grab the relevant entry from this map. This eliminates a bunch of awkward state tracking during construction of the module graph. It's also now clearer exactly what options the builtin module has, since previously it inherited some options arbitrarily from the first-created module with that "builtin" module! The user-visible effects of this commit are: * retryable file errors are now consistently reported against the whole file, with a note pointing to a live import of that file * some theoretical bugs where imports are wrongly considered distinct (when the import path moves out of the cwd and then back in) are fixed * some consistency issues with how file-level errors are reported are fixed; these errors will now always be printed in the same order regardless of how the AstGen pass assigns file indices * incremental updates do not print retryable file errors differently between updates or depending on file structure/contents * incremental updates support files changing modules * incremental updates support files becoming unreferenced Resolves: #22696

49 files changed, 2746 insertions(+), 2377 deletions(-)

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,
...@@ -17290,10 +17301,10 @@ fn zirClosureGet(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat...@@ -17290,10 +17301,10 @@ fn zirClosureGet(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat
17290 const name = name: {17301 const name = name: {
17291 // TODO: we should probably store this name in the ZIR to avoid this complexity.17302 // TODO: we should probably store this name in the ZIR to avoid this complexity.
17292 const file, const src_base_node = Zcu.LazySrcLoc.resolveBaseNode(block.src_base_inst, zcu).?;17303 const file, const src_base_node = Zcu.LazySrcLoc.resolveBaseNode(block.src_base_inst, zcu).?;
17293 const tree = file.getTree(sema.gpa) catch |err| {17304 const tree = file.getTree(zcu) catch |err| {
17294 // In this case we emit a warning + a less precise source location.17305 // In this case we emit a warning + a less precise source location.
17295 log.warn("unable to load {s}: {s}", .{17306 log.warn("unable to load {}: {s}", .{
17296 file.sub_file_path, @errorName(err),17307 file.path.fmt(zcu.comp), @errorName(err),
17297 });17308 });
17298 break :name null;17309 break :name null;
17299 };17310 };
...@@ -17318,10 +17329,10 @@ fn zirClosureGet(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat...@@ -17318,10 +17329,10 @@ fn zirClosureGet(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat
17318 const msg = msg: {17329 const msg = msg: {
17319 const name = name: {17330 const name = name: {
17320 const file, const src_base_node = Zcu.LazySrcLoc.resolveBaseNode(block.src_base_inst, zcu).?;17331 const file, const src_base_node = Zcu.LazySrcLoc.resolveBaseNode(block.src_base_inst, zcu).?;
17321 const tree = file.getTree(sema.gpa) catch |err| {17332 const tree = file.getTree(zcu) catch |err| {
17322 // In this case we emit a warning + a less precise source location.17333 // In this case we emit a warning + a less precise source location.
17323 log.warn("unable to load {s}: {s}", .{17334 log.warn("unable to load {}: {s}", .{
17324 file.sub_file_path, @errorName(err),17335 file.path.fmt(zcu.comp), @errorName(err),
17325 });17336 });
17326 break :name null;17337 break :name null;
17327 };17338 };
...@@ -17415,7 +17426,7 @@ fn zirBuiltinSrc(...@@ -17415,7 +17426,7 @@ fn zirBuiltinSrc(
17415 };17426 };
1741617427
17417 const module_name_val = v: {17428 const module_name_val = v: {
17418 const module_name = file_scope.mod.fully_qualified_name;17429 const module_name = file_scope.mod.?.fully_qualified_name;
17419 const array_ty = try pt.intern(.{ .array_type = .{17430 const array_ty = try pt.intern(.{ .array_type = .{
17420 .len = module_name.len,17431 .len = module_name.len,
17421 .sentinel = .zero_u8,17432 .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);
...@@ -3404,27 +3490,21 @@ pub fn ensureNavValAnalysisQueued(zcu: *Zcu, nav_id: InternPool.Nav.Index) !void...@@ -3404,27 +3490,21 @@ pub fn ensureNavValAnalysisQueued(zcu: *Zcu, nav_id: InternPool.Nav.Index) !void
3404 zcu.nav_val_analysis_queued.putAssumeCapacityNoClobber(nav_id, {});3490 zcu.nav_val_analysis_queued.putAssumeCapacityNoClobber(nav_id, {});
3405}3491}
34063492
3407pub const ImportFileResult = struct {3493pub const ImportResult = struct {
3408 file: *File,3494 /// Whether `file` has been newly created; in other words, whether this is the first import of
3409 file_index: File.Index,3495 /// this file. This should only be `true` when importing files during AstGen. After that, all
3496 /// files should have already been discovered.
3410 is_new: bool,3497 is_new: bool,
3411 is_pkg: bool,
3412};
34133498
3414pub fn computePathDigest(zcu: *Zcu, mod: *Package.Module, sub_file_path: []const u8) Cache.BinDigest {3499 /// `file.mod` is not populated by this function, so if `is_new`, then it is `undefined`.
3415 const want_local_cache = mod == zcu.main_mod;3500 file: *Zcu.File,
3416 var path_hash: Cache.HashHelper = .{};3501 file_index: File.Index,
3417 path_hash.addBytes(build_options.version);3502
3418 path_hash.add(builtin.zig_backend);3503 /// If this import was a simple file path, this is `null`; the imported file should exist within
3419 if (!want_local_cache) {3504 /// the importer's module. Otherwise, it's the module which the import resolved to. This module
3420 path_hash.addOptionalBytes(mod.root.root_dir.path);3505 /// could match the module of `cur_file`, since a module can depend on itself.
3421 path_hash.addBytes(mod.root.sub_path);3506 module: ?*Package.Module,
3422 }3507};
3423 path_hash.addBytes(sub_file_path);
3424 var bin: Cache.BinDigest = undefined;
3425 path_hash.hasher.final(&bin);
3426 return bin;
3427}
34283508
3429/// Delete all the Export objects that are caused by this `AnalUnit`. Re-analysis of3509/// Delete all the Export objects that are caused by this `AnalUnit`. Re-analysis of
3430/// this `AnalUnit` will cause them to be re-created (or not).3510/// this `AnalUnit` will cause them to be re-created (or not).
...@@ -3938,15 +4018,7 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv...@@ -3938,15 +4018,7 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv
39384018
3939 try type_queue.ensureTotalCapacity(gpa, zcu.analysis_roots.len);4019 try type_queue.ensureTotalCapacity(gpa, zcu.analysis_roots.len);
3940 for (zcu.analysis_roots.slice()) |mod| {4020 for (zcu.analysis_roots.slice()) |mod| {
3941 // Logic ripped from `Zcu.PerThread.importPkg`.4021 const file = zcu.module_roots.get(mod).?.unwrap() orelse continue;
3942 // TODO: this is silly, `Module` should just store a reference to its root `File`.
3943 const resolved_path = try std.fs.path.resolve(gpa, &.{
3944 mod.root.root_dir.path orelse ".",
3945 mod.root.sub_path,
3946 mod.root_src_path,
3947 });
3948 defer gpa.free(resolved_path);
3949 const file = zcu.import_table.get(resolved_path).?;
3950 const root_ty = zcu.fileRootType(file);4022 const root_ty = zcu.fileRootType(file);
3951 if (root_ty == .none) continue;4023 if (root_ty == .none) continue;
3952 type_queue.putAssumeCapacityNoClobber(root_ty, null);4024 type_queue.putAssumeCapacityNoClobber(root_ty, null);
...@@ -4226,8 +4298,8 @@ fn formatAnalUnit(data: struct { unit: AnalUnit, zcu: *Zcu }, comptime fmt: []co...@@ -4226,8 +4298,8 @@ fn formatAnalUnit(data: struct { unit: AnalUnit, zcu: *Zcu }, comptime fmt: []co
4226 .@"comptime" => |cu_id| {4298 .@"comptime" => |cu_id| {
4227 const cu = ip.getComptimeUnit(cu_id);4299 const cu = ip.getComptimeUnit(cu_id);
4228 if (cu.zir_index.resolveFull(ip)) |resolved| {4300 if (cu.zir_index.resolveFull(ip)) |resolved| {
4229 const file_path = zcu.fileByIndex(resolved.file).sub_file_path;4301 const file_path = zcu.fileByIndex(resolved.file).path;
4230 return writer.print("comptime(inst=('{s}', %{}) [{}])", .{ file_path, @intFromEnum(resolved.inst), @intFromEnum(cu_id) });4302 return writer.print("comptime(inst=('{}', %{}) [{}])", .{ file_path.fmt(zcu.comp), @intFromEnum(resolved.inst), @intFromEnum(cu_id) });
4231 } else {4303 } else {
4232 return writer.print("comptime(inst=<lost> [{}])", .{@intFromEnum(cu_id)});4304 return writer.print("comptime(inst=<lost> [{}])", .{@intFromEnum(cu_id)});
4233 }4305 }
...@@ -4251,8 +4323,8 @@ fn formatDependee(data: struct { dependee: InternPool.Dependee, zcu: *Zcu }, com...@@ -4251,8 +4323,8 @@ fn formatDependee(data: struct { dependee: InternPool.Dependee, zcu: *Zcu }, com
4251 const info = ti.resolveFull(ip) orelse {4323 const info = ti.resolveFull(ip) orelse {
4252 return writer.writeAll("inst(<lost>)");4324 return writer.writeAll("inst(<lost>)");
4253 };4325 };
4254 const file_path = zcu.fileByIndex(info.file).sub_file_path;4326 const file_path = zcu.fileByIndex(info.file).path;
4255 return writer.print("inst('{s}', %{d})", .{ file_path, @intFromEnum(info.inst) });4327 return writer.print("inst('{}', %{d})", .{ file_path.fmt(zcu.comp), @intFromEnum(info.inst) });
4256 },4328 },
4257 .nav_val => |nav| {4329 .nav_val => |nav| {
4258 const fqn = ip.getNav(nav).fqn;4330 const fqn = ip.getNav(nav).fqn;
...@@ -4268,30 +4340,26 @@ fn formatDependee(data: struct { dependee: InternPool.Dependee, zcu: *Zcu }, com...@@ -4268,30 +4340,26 @@ fn formatDependee(data: struct { dependee: InternPool.Dependee, zcu: *Zcu }, com
4268 else => unreachable,4340 else => unreachable,
4269 },4341 },
4270 .zon_file => |file| {4342 .zon_file => |file| {
4271 const file_path = zcu.fileByIndex(file).sub_file_path;4343 const file_path = zcu.fileByIndex(file).path;
4272 return writer.print("zon_file('{s}')", .{file_path});4344 return writer.print("zon_file('{}')", .{file_path.fmt(zcu.comp)});
4273 },4345 },
4274 .embed_file => |ef_idx| {4346 .embed_file => |ef_idx| {
4275 const ef = ef_idx.get(zcu);4347 const ef = ef_idx.get(zcu);
4276 return writer.print("embed_file('{s}')", .{std.fs.path.fmtJoin(&.{4348 return writer.print("embed_file('{}')", .{ef.path.fmt(zcu.comp)});
4277 ef.owner.root.root_dir.path orelse "",
4278 ef.owner.root.sub_path,
4279 ef.sub_file_path.toSlice(ip),
4280 })});
4281 },4349 },
4282 .namespace => |ti| {4350 .namespace => |ti| {
4283 const info = ti.resolveFull(ip) orelse {4351 const info = ti.resolveFull(ip) orelse {
4284 return writer.writeAll("namespace(<lost>)");4352 return writer.writeAll("namespace(<lost>)");
4285 };4353 };
4286 const file_path = zcu.fileByIndex(info.file).sub_file_path;4354 const file_path = zcu.fileByIndex(info.file).path;
4287 return writer.print("namespace('{s}', %{d})", .{ file_path, @intFromEnum(info.inst) });4355 return writer.print("namespace('{}', %{d})", .{ file_path.fmt(zcu.comp), @intFromEnum(info.inst) });
4288 },4356 },
4289 .namespace_name => |k| {4357 .namespace_name => |k| {
4290 const info = k.namespace.resolveFull(ip) orelse {4358 const info = k.namespace.resolveFull(ip) orelse {
4291 return writer.print("namespace(<lost>, '{}')", .{k.name.fmt(ip)});4359 return writer.print("namespace(<lost>, '{}')", .{k.name.fmt(ip)});
4292 };4360 };
4293 const file_path = zcu.fileByIndex(info.file).sub_file_path;4361 const file_path = zcu.fileByIndex(info.file).path;
4294 return writer.print("namespace('{s}', %{d}, '{}')", .{ file_path, @intFromEnum(info.inst), k.name.fmt(ip) });4362 return writer.print("namespace('{}', %{d}, '{}')", .{ file_path.fmt(zcu.comp), @intFromEnum(info.inst), k.name.fmt(ip) });
4295 },4363 },
4296 .memoized_state => return writer.writeAll("memoized_state"),4364 .memoized_state => return writer.writeAll("memoized_state"),
4297 }4365 }
...@@ -4508,3 +4576,114 @@ pub fn codegenFailTypeMsg(zcu: *Zcu, ty_index: InternPool.Index, msg: *ErrorMsg)...@@ -4508,3 +4576,114 @@ pub fn codegenFailTypeMsg(zcu: *Zcu, ty_index: InternPool.Index, msg: *ErrorMsg)
4508 zcu.failed_types.putAssumeCapacityNoClobber(ty_index, msg);4576 zcu.failed_types.putAssumeCapacityNoClobber(ty_index, msg);
4509 return error.CodegenFail;4577 return error.CodegenFail;
4510}4578}
4579
4580/// Asserts that `zcu.multi_module_err != null`.
4581pub fn addFileInMultipleModulesError(
4582 zcu: *Zcu,
4583 eb: *std.zig.ErrorBundle.Wip,
4584) !void {
4585 const gpa = zcu.gpa;
4586
4587 const info = zcu.multi_module_err.?;
4588 const file = info.file;
4589
4590 // error: file exists in modules 'root.foo' and 'root.bar'
4591 // note: files must belong to only one module
4592 // note: file is imported here
4593 // note: which is imported here
4594 // note: which is the root of module 'root.foo' imported here
4595 // note: file is the root of module 'root.bar' imported here
4596
4597 const file_src = try zcu.fileByIndex(file).errorBundleWholeFileSrc(zcu, eb);
4598 const root_msg = try eb.printString("file exists in modules '{s}' and '{s}'", .{
4599 info.modules[0].fully_qualified_name,
4600 info.modules[1].fully_qualified_name,
4601 });
4602
4603 var notes: std.ArrayListUnmanaged(std.zig.ErrorBundle.MessageIndex) = .empty;
4604 defer notes.deinit(gpa);
4605
4606 try notes.append(gpa, try eb.addErrorMessage(.{
4607 .msg = try eb.addString("files must belong to only one module"),
4608 .src_loc = file_src,
4609 }));
4610
4611 try zcu.explainWhyFileIsInModule(eb, &notes, file, info.modules[0], info.refs[0]);
4612 try zcu.explainWhyFileIsInModule(eb, &notes, file, info.modules[1], info.refs[1]);
4613
4614 try eb.addRootErrorMessage(.{
4615 .msg = root_msg,
4616 .src_loc = file_src,
4617 .notes_len = @intCast(notes.items.len),
4618 });
4619 const notes_start = try eb.reserveNotes(@intCast(notes.items.len));
4620 const notes_slice: []std.zig.ErrorBundle.MessageIndex = @ptrCast(eb.extra.items[notes_start..]);
4621 @memcpy(notes_slice, notes.items);
4622}
4623
4624fn explainWhyFileIsInModule(
4625 zcu: *Zcu,
4626 eb: *std.zig.ErrorBundle.Wip,
4627 notes_out: *std.ArrayListUnmanaged(std.zig.ErrorBundle.MessageIndex),
4628 file: File.Index,
4629 in_module: *Package.Module,
4630 ref: File.Reference,
4631) !void {
4632 const gpa = zcu.gpa;
4633
4634 // error: file is the root of module 'foo'
4635 //
4636 // error: file is imported here by the root of module 'foo'
4637 //
4638 // error: file is imported here
4639 // note: which is imported here
4640 // note: which is imported here by the root of module 'foo'
4641
4642 var import = switch (ref) {
4643 .analysis_root => |mod| {
4644 assert(mod == in_module);
4645 try notes_out.append(gpa, try eb.addErrorMessage(.{
4646 .msg = try eb.printString("file is the root of module '{s}'", .{mod.fully_qualified_name}),
4647 .src_loc = try zcu.fileByIndex(file).errorBundleWholeFileSrc(zcu, eb),
4648 }));
4649 return;
4650 },
4651 .import => |import| if (import.module) |mod| {
4652 assert(mod == in_module);
4653 try notes_out.append(gpa, try eb.addErrorMessage(.{
4654 .msg = try eb.printString("file is the root of module '{s}'", .{mod.fully_qualified_name}),
4655 .src_loc = try zcu.fileByIndex(file).errorBundleWholeFileSrc(zcu, eb),
4656 }));
4657 return;
4658 } else import,
4659 };
4660
4661 var is_first = true;
4662 while (true) {
4663 const thing: []const u8 = if (is_first) "file" else "which";
4664 is_first = false;
4665
4666 const import_src = try zcu.fileByIndex(import.importer).errorBundleTokenSrc(import.tok, zcu, eb);
4667
4668 const importer_ref = zcu.alive_files.get(import.importer).?;
4669 const importer_root: ?*Package.Module = switch (importer_ref) {
4670 .analysis_root => |mod| mod,
4671 .import => |i| i.module,
4672 };
4673
4674 if (importer_root) |m| {
4675 try notes_out.append(gpa, try eb.addErrorMessage(.{
4676 .msg = try eb.printString("{s} is imported here by the root of module '{s}'", .{ thing, m.fully_qualified_name }),
4677 .src_loc = import_src,
4678 }));
4679 return;
4680 }
4681
4682 try notes_out.append(gpa, try eb.addErrorMessage(.{
4683 .msg = try eb.printString("{s} is imported here", .{thing}),
4684 .src_loc = import_src,
4685 }));
4686
4687 import = importer_ref.import;
4688 }
4689}
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
...@@ -892,7 +892,7 @@ pub fn generate(...@@ -892,7 +892,7 @@ pub fn generate(
892 const ip = &zcu.intern_pool;892 const ip = &zcu.intern_pool;
893 const func = zcu.funcInfo(func_index);893 const func = zcu.funcInfo(func_index);
894 const fn_type: Type = .fromInterned(func.ty);894 const fn_type: Type = .fromInterned(func.ty);
895 const mod = zcu.navFileScope(func.owner_nav).mod;895 const mod = zcu.navFileScope(func.owner_nav).mod.?;
896896
897 var function: CodeGen = .{897 var function: CodeGen = .{
898 .gpa = gpa,898 .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