| author | |
| committer | |
| log | f01f1e33c96f0b00db8e036a654c1b3bf8531cd8 |
| tree | 3daca71f83a02d73d4c93d973d7022776e476274 |
| parent | cf059ee08716300e924bced08ebdd5bd8f97d789 |
| parent | bebfa036ba52076cd03f9ef943f61da64ba6e97b |
| signature |
ZON and incremental bits16 files changed, 788 insertions(+), 587 deletions(-)
lib/std/zig/Zoir.zig+25| ... | ... | @@ -10,6 +10,31 @@ string_bytes: []u8, |
| 10 | 10 | compile_errors: []Zoir.CompileError, |
| 11 | 11 | error_notes: []Zoir.CompileError.Note, |
| 12 | 12 | |
| 13 | /// The data stored at byte offset 0 when ZOIR is stored in a file. | |
| 14 | pub const Header = extern struct { | |
| 15 | nodes_len: u32, | |
| 16 | extra_len: u32, | |
| 17 | limbs_len: u32, | |
| 18 | string_bytes_len: u32, | |
| 19 | compile_errors_len: u32, | |
| 20 | error_notes_len: u32, | |
| 21 | ||
| 22 | /// We could leave this as padding, however it triggers a Valgrind warning because | |
| 23 | /// we read and write undefined bytes to the file system. This is harmless, but | |
| 24 | /// it's essentially free to have a zero field here and makes the warning go away, | |
| 25 | /// making it more likely that following Valgrind warnings will be taken seriously. | |
| 26 | unused: u64 = 0, | |
| 27 | ||
| 28 | stat_inode: std.fs.File.INode, | |
| 29 | stat_size: u64, | |
| 30 | stat_mtime: i128, | |
| 31 | ||
| 32 | comptime { | |
| 33 | // Check that `unused` is working as expected | |
| 34 | assert(std.meta.hasUniqueRepresentation(Header)); | |
| 35 | } | |
| 36 | }; | |
| 37 | ||
| 13 | 38 | pub fn hasCompileErrors(zoir: Zoir) bool { |
| 14 | 39 | if (zoir.compile_errors.len > 0) { |
| 15 | 40 | assert(zoir.nodes.len == 0); |
src/Builtin.zig+10-14| ... | ... | @@ -264,14 +264,12 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void { |
| 264 | 264 | } |
| 265 | 265 | |
| 266 | 266 | pub fn populateFile(comp: *Compilation, mod: *Module, file: *File) !void { |
| 267 | assert(file.source_loaded == true); | |
| 268 | ||
| 269 | 267 | if (mod.root.statFile(mod.root_src_path)) |stat| { |
| 270 | if (stat.size != file.source.len) { | |
| 268 | if (stat.size != file.source.?.len) { | |
| 271 | 269 | std.log.warn( |
| 272 | 270 | "the cached file '{}{s}' had the wrong size. Expected {d}, found {d}. " ++ |
| 273 | 271 | "Overwriting with correct file contents now", |
| 274 | .{ mod.root, mod.root_src_path, file.source.len, stat.size }, | |
| 272 | .{ mod.root, mod.root_src_path, file.source.?.len, stat.size }, | |
| 275 | 273 | ); |
| 276 | 274 | |
| 277 | 275 | try writeFile(file, mod); |
| ... | ... | @@ -296,15 +294,13 @@ pub fn populateFile(comp: *Compilation, mod: *Module, file: *File) !void { |
| 296 | 294 | |
| 297 | 295 | log.debug("parsing and generating '{s}'", .{mod.root_src_path}); |
| 298 | 296 | |
| 299 | file.tree = try std.zig.Ast.parse(comp.gpa, file.source, .zig); | |
| 300 | assert(file.tree.errors.len == 0); // builtin.zig must parse | |
| 301 | file.tree_loaded = 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 | |
| 302 | 299 | |
| 303 | file.zir = try AstGen.generate(comp.gpa, file.tree); | |
| 304 | assert(!file.zir.hasCompileErrors()); // builtin.zig must not have astgen errors | |
| 305 | file.zir_loaded = true; | |
| 306 | file.status = .success_zir; | |
| 307 | // Note that whilst we set `zir_loaded` here, we populated `path_digest` | |
| 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` | |
| 308 | 304 | // all the way back in `Package.Module.create`. |
| 309 | 305 | } |
| 310 | 306 | |
| ... | ... | @@ -312,7 +308,7 @@ fn writeFile(file: *File, mod: *Module) !void { |
| 312 | 308 | var buf: [std.fs.max_path_bytes]u8 = undefined; |
| 313 | 309 | var af = try mod.root.atomicFile(mod.root_src_path, .{ .make_path = true }, &buf); |
| 314 | 310 | defer af.deinit(); |
| 315 | try af.file.writeAll(file.source); | |
| 311 | try af.file.writeAll(file.source.?); | |
| 316 | 312 | af.finish() catch |err| switch (err) { |
| 317 | 313 | error.AccessDenied => switch (builtin.os.tag) { |
| 318 | 314 | .windows => { |
| ... | ... | @@ -326,7 +322,7 @@ fn writeFile(file: *File, mod: *Module) !void { |
| 326 | 322 | }; |
| 327 | 323 | |
| 328 | 324 | file.stat = .{ |
| 329 | .size = file.source.len, | |
| 325 | .size = file.source.?.len, | |
| 330 | 326 | .inode = 0, // dummy value |
| 331 | 327 | .mtime = 0, // dummy value |
| 332 | 328 | }; |
src/Compilation.zig+92-54| ... | ... | @@ -2220,10 +2220,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void { |
| 2220 | 2220 | try comp.astgen_work_queue.ensureUnusedCapacity(zcu.import_table.count()); |
| 2221 | 2221 | for (zcu.import_table.values()) |file_index| { |
| 2222 | 2222 | if (zcu.fileByIndex(file_index).mod.isBuiltin()) continue; |
| 2223 | const file = zcu.fileByIndex(file_index); | |
| 2224 | if (file.getMode() == .zig) { | |
| 2225 | comp.astgen_work_queue.writeItemAssumeCapacity(file_index); | |
| 2226 | } | |
| 2223 | comp.astgen_work_queue.writeItemAssumeCapacity(file_index); | |
| 2227 | 2224 | } |
| 2228 | 2225 | if (comp.file_system_inputs) |fsi| { |
| 2229 | 2226 | for (zcu.import_table.values()) |file_index| { |
| ... | ... | @@ -2906,10 +2903,12 @@ pub fn makeBinFileWritable(comp: *Compilation) !void { |
| 2906 | 2903 | const Header = extern struct { |
| 2907 | 2904 | intern_pool: extern struct { |
| 2908 | 2905 | thread_count: u32, |
| 2909 | file_deps_len: u32, | |
| 2910 | 2906 | src_hash_deps_len: u32, |
| 2911 | 2907 | nav_val_deps_len: u32, |
| 2912 | 2908 | nav_ty_deps_len: u32, |
| 2909 | interned_deps_len: u32, | |
| 2910 | zon_file_deps_len: u32, | |
| 2911 | embed_file_deps_len: u32, | |
| 2913 | 2912 | namespace_deps_len: u32, |
| 2914 | 2913 | namespace_name_deps_len: u32, |
| 2915 | 2914 | first_dependency_len: u32, |
| ... | ... | @@ -2950,10 +2949,12 @@ pub fn saveState(comp: *Compilation) !void { |
| 2950 | 2949 | const header: Header = .{ |
| 2951 | 2950 | .intern_pool = .{ |
| 2952 | 2951 | .thread_count = @intCast(ip.locals.len), |
| 2953 | .file_deps_len = @intCast(ip.file_deps.count()), | |
| 2954 | 2952 | .src_hash_deps_len = @intCast(ip.src_hash_deps.count()), |
| 2955 | 2953 | .nav_val_deps_len = @intCast(ip.nav_val_deps.count()), |
| 2956 | 2954 | .nav_ty_deps_len = @intCast(ip.nav_ty_deps.count()), |
| 2955 | .interned_deps_len = @intCast(ip.interned_deps.count()), | |
| 2956 | .zon_file_deps_len = @intCast(ip.zon_file_deps.count()), | |
| 2957 | .embed_file_deps_len = @intCast(ip.embed_file_deps.count()), | |
| 2957 | 2958 | .namespace_deps_len = @intCast(ip.namespace_deps.count()), |
| 2958 | 2959 | .namespace_name_deps_len = @intCast(ip.namespace_name_deps.count()), |
| 2959 | 2960 | .first_dependency_len = @intCast(ip.first_dependency.count()), |
| ... | ... | @@ -2978,14 +2979,18 @@ pub fn saveState(comp: *Compilation) !void { |
| 2978 | 2979 | addBuf(&bufs, mem.asBytes(&header)); |
| 2979 | 2980 | addBuf(&bufs, mem.sliceAsBytes(pt_headers.items)); |
| 2980 | 2981 | |
| 2981 | addBuf(&bufs, mem.sliceAsBytes(ip.file_deps.keys())); | |
| 2982 | addBuf(&bufs, mem.sliceAsBytes(ip.file_deps.values())); | |
| 2983 | 2982 | addBuf(&bufs, mem.sliceAsBytes(ip.src_hash_deps.keys())); |
| 2984 | 2983 | addBuf(&bufs, mem.sliceAsBytes(ip.src_hash_deps.values())); |
| 2985 | 2984 | addBuf(&bufs, mem.sliceAsBytes(ip.nav_val_deps.keys())); |
| 2986 | 2985 | addBuf(&bufs, mem.sliceAsBytes(ip.nav_val_deps.values())); |
| 2987 | 2986 | addBuf(&bufs, mem.sliceAsBytes(ip.nav_ty_deps.keys())); |
| 2988 | 2987 | addBuf(&bufs, mem.sliceAsBytes(ip.nav_ty_deps.values())); |
| 2988 | addBuf(&bufs, mem.sliceAsBytes(ip.interned_deps.keys())); | |
| 2989 | addBuf(&bufs, mem.sliceAsBytes(ip.interned_deps.values())); | |
| 2990 | addBuf(&bufs, mem.sliceAsBytes(ip.zon_file_deps.keys())); | |
| 2991 | addBuf(&bufs, mem.sliceAsBytes(ip.zon_file_deps.values())); | |
| 2992 | addBuf(&bufs, mem.sliceAsBytes(ip.embed_file_deps.keys())); | |
| 2993 | addBuf(&bufs, mem.sliceAsBytes(ip.embed_file_deps.values())); | |
| 2989 | 2994 | addBuf(&bufs, mem.sliceAsBytes(ip.namespace_deps.keys())); |
| 2990 | 2995 | addBuf(&bufs, mem.sliceAsBytes(ip.namespace_deps.values())); |
| 2991 | 2996 | addBuf(&bufs, mem.sliceAsBytes(ip.namespace_name_deps.keys())); |
| ... | ... | @@ -3203,15 +3208,13 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle { |
| 3203 | 3208 | } |
| 3204 | 3209 | |
| 3205 | 3210 | if (comp.zcu) |zcu| { |
| 3206 | const ip = &zcu.intern_pool; | |
| 3207 | ||
| 3208 | 3211 | for (zcu.failed_files.keys(), zcu.failed_files.values()) |file, error_msg| { |
| 3209 | 3212 | if (error_msg) |msg| { |
| 3210 | 3213 | try addModuleErrorMsg(zcu, &bundle, msg.*); |
| 3211 | 3214 | } else { |
| 3212 | 3215 | // Must be ZIR or Zoir errors. Note that this may include AST errors. |
| 3213 | 3216 | _ = try file.getTree(gpa); // Tree must be loaded. |
| 3214 | if (file.zir_loaded) { | |
| 3217 | if (file.zir != null) { | |
| 3215 | 3218 | try addZirErrorMessages(&bundle, file); |
| 3216 | 3219 | } else if (file.zoir != null) { |
| 3217 | 3220 | try addZoirErrorMessages(&bundle, file); |
| ... | ... | @@ -3277,20 +3280,6 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle { |
| 3277 | 3280 | if (!refs.contains(anal_unit)) continue; |
| 3278 | 3281 | } |
| 3279 | 3282 | |
| 3280 | report_ok: { | |
| 3281 | const file_index = switch (anal_unit.unwrap()) { | |
| 3282 | .@"comptime" => |cu| ip.getComptimeUnit(cu).zir_index.resolveFile(ip), | |
| 3283 | .nav_val, .nav_ty => |nav| ip.getNav(nav).analysis.?.zir_index.resolveFile(ip), | |
| 3284 | .type => |ty| Type.fromInterned(ty).typeDeclInst(zcu).?.resolveFile(ip), | |
| 3285 | .func => |ip_index| zcu.funcInfo(ip_index).zir_body_inst.resolveFile(ip), | |
| 3286 | .memoized_state => break :report_ok, // always report std.builtin errors | |
| 3287 | }; | |
| 3288 | ||
| 3289 | // Skip errors for AnalUnits within files that had a parse failure. | |
| 3290 | // We'll try again once parsing succeeds. | |
| 3291 | if (!zcu.fileByIndex(file_index).okToReportErrors()) continue; | |
| 3292 | } | |
| 3293 | ||
| 3294 | 3283 | std.log.scoped(.zcu).debug("analysis error '{s}' reported from unit '{}'", .{ |
| 3295 | 3284 | error_msg.msg, |
| 3296 | 3285 | zcu.fmtAnalUnit(anal_unit), |
| ... | ... | @@ -3318,12 +3307,10 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle { |
| 3318 | 3307 | } |
| 3319 | 3308 | } |
| 3320 | 3309 | } |
| 3321 | for (zcu.failed_codegen.keys(), zcu.failed_codegen.values()) |nav, error_msg| { | |
| 3322 | if (!zcu.navFileScope(nav).okToReportErrors()) continue; | |
| 3310 | for (zcu.failed_codegen.values()) |error_msg| { | |
| 3323 | 3311 | try addModuleErrorMsg(zcu, &bundle, error_msg.*); |
| 3324 | 3312 | } |
| 3325 | for (zcu.failed_types.keys(), zcu.failed_types.values()) |ty_index, error_msg| { | |
| 3326 | if (!zcu.typeFileScope(ty_index).okToReportErrors()) continue; | |
| 3313 | for (zcu.failed_types.values()) |error_msg| { | |
| 3327 | 3314 | try addModuleErrorMsg(zcu, &bundle, error_msg.*); |
| 3328 | 3315 | } |
| 3329 | 3316 | for (zcu.failed_exports.values()) |value| { |
| ... | ... | @@ -3623,22 +3610,17 @@ pub fn addModuleErrorMsg( |
| 3623 | 3610 | } |
| 3624 | 3611 | |
| 3625 | 3612 | pub fn addZirErrorMessages(eb: *ErrorBundle.Wip, file: *Zcu.File) !void { |
| 3626 | assert(file.zir_loaded); | |
| 3627 | assert(file.tree_loaded); | |
| 3628 | assert(file.source_loaded); | |
| 3629 | 3613 | const gpa = eb.gpa; |
| 3630 | 3614 | const src_path = try file.fullPath(gpa); |
| 3631 | 3615 | defer gpa.free(src_path); |
| 3632 | return eb.addZirErrorMessages(file.zir, file.tree, file.source, src_path); | |
| 3616 | return eb.addZirErrorMessages(file.zir.?, file.tree.?, file.source.?, src_path); | |
| 3633 | 3617 | } |
| 3634 | 3618 | |
| 3635 | 3619 | pub fn addZoirErrorMessages(eb: *ErrorBundle.Wip, file: *Zcu.File) !void { |
| 3636 | assert(file.source_loaded); | |
| 3637 | assert(file.tree_loaded); | |
| 3638 | 3620 | const gpa = eb.gpa; |
| 3639 | 3621 | const src_path = try file.fullPath(gpa); |
| 3640 | 3622 | defer gpa.free(src_path); |
| 3641 | return eb.addZoirErrorMessages(file.zoir.?, file.tree, file.source, src_path); | |
| 3623 | return eb.addZoirErrorMessages(file.zoir.?, file.tree.?, file.source.?, src_path); | |
| 3642 | 3624 | } |
| 3643 | 3625 | |
| 3644 | 3626 | pub fn performAllTheWork( |
| ... | ... | @@ -3802,7 +3784,7 @@ fn performAllTheWorkInner( |
| 3802 | 3784 | // will be needed by the worker threads. |
| 3803 | 3785 | const path_digest = zcu.filePathDigest(file_index); |
| 3804 | 3786 | const file = zcu.fileByIndex(file_index); |
| 3805 | comp.thread_pool.spawnWgId(&astgen_wait_group, workerAstGenFile, .{ | |
| 3787 | comp.thread_pool.spawnWgId(&astgen_wait_group, workerUpdateFile, .{ | |
| 3806 | 3788 | comp, file, file_index, path_digest, zir_prog_node, &astgen_wait_group, .root, |
| 3807 | 3789 | }); |
| 3808 | 3790 | } |
| ... | ... | @@ -3810,7 +3792,7 @@ fn performAllTheWorkInner( |
| 3810 | 3792 | |
| 3811 | 3793 | for (0.., zcu.embed_table.values()) |ef_index_usize, ef| { |
| 3812 | 3794 | const ef_index: Zcu.EmbedFile.Index = @enumFromInt(ef_index_usize); |
| 3813 | comp.thread_pool.spawnWgId(&astgen_wait_group, workerCheckEmbedFile, .{ | |
| 3795 | comp.thread_pool.spawnWgId(&astgen_wait_group, workerUpdateEmbedFile, .{ | |
| 3814 | 3796 | comp, ef_index, ef, |
| 3815 | 3797 | }); |
| 3816 | 3798 | } |
| ... | ... | @@ -3832,12 +3814,64 @@ fn performAllTheWorkInner( |
| 3832 | 3814 | if (comp.zcu) |zcu| { |
| 3833 | 3815 | const pt: Zcu.PerThread = .activate(zcu, .main); |
| 3834 | 3816 | defer pt.deactivate(); |
| 3817 | ||
| 3818 | // If the cache mode is `whole`, then add every source file to the cache manifest. | |
| 3819 | switch (comp.cache_use) { | |
| 3820 | .whole => |whole| if (whole.cache_manifest) |man| { | |
| 3821 | const gpa = zcu.gpa; | |
| 3822 | for (zcu.import_table.values()) |file_index| { | |
| 3823 | const file = zcu.fileByIndex(file_index); | |
| 3824 | const source = file.getSource(gpa) catch |err| { | |
| 3825 | try pt.reportRetryableFileError(file_index, "unable to load source: {s}", .{@errorName(err)}); | |
| 3826 | continue; | |
| 3827 | }; | |
| 3828 | const resolved_path = try std.fs.path.resolve(gpa, &.{ | |
| 3829 | file.mod.root.root_dir.path orelse ".", | |
| 3830 | file.mod.root.sub_path, | |
| 3831 | file.sub_file_path, | |
| 3832 | }); | |
| 3833 | errdefer gpa.free(resolved_path); | |
| 3834 | whole.cache_manifest_mutex.lock(); | |
| 3835 | defer whole.cache_manifest_mutex.unlock(); | |
| 3836 | man.addFilePostContents(resolved_path, source.bytes, source.stat) catch |err| switch (err) { | |
| 3837 | error.OutOfMemory => |e| return e, | |
| 3838 | else => { | |
| 3839 | try pt.reportRetryableFileError(file_index, "unable to update cache: {s}", .{@errorName(err)}); | |
| 3840 | continue; | |
| 3841 | }, | |
| 3842 | }; | |
| 3843 | } | |
| 3844 | }, | |
| 3845 | .incremental => {}, | |
| 3846 | } | |
| 3847 | ||
| 3848 | try reportMultiModuleErrors(pt); | |
| 3849 | ||
| 3850 | const any_fatal_files = for (zcu.import_table.values()) |file_index| { | |
| 3851 | const file = zcu.fileByIndex(file_index); | |
| 3852 | switch (file.status) { | |
| 3853 | .never_loaded => unreachable, // everything is loaded by the workers | |
| 3854 | .retryable_failure, .astgen_failure => break true, | |
| 3855 | .success => {}, | |
| 3856 | } | |
| 3857 | } else false; | |
| 3858 | ||
| 3859 | if (any_fatal_files or comp.alloc_failure_occurred) { | |
| 3860 | // We give up right now! No updating of ZIR refs, no nothing. The idea is that this prevents | |
| 3861 | // us from invalidating lots of incremental dependencies due to files with e.g. parse errors. | |
| 3862 | // However, this means our analysis data is invalid, so we want to omit all analysis errors. | |
| 3863 | // To do that, let's just clear the analysis roots! | |
| 3864 | ||
| 3865 | assert(zcu.failed_files.count() > 0); // we will get an error | |
| 3866 | zcu.analysis_roots.clear(); // no analysis happened | |
| 3867 | return; | |
| 3868 | } | |
| 3869 | ||
| 3835 | 3870 | if (comp.incremental) { |
| 3836 | 3871 | const update_zir_refs_node = main_progress_node.start("Update ZIR References", 0); |
| 3837 | 3872 | defer update_zir_refs_node.end(); |
| 3838 | 3873 | try pt.updateZirRefs(); |
| 3839 | 3874 | } |
| 3840 | try reportMultiModuleErrors(pt); | |
| 3841 | 3875 | try zcu.flushRetryableFailures(); |
| 3842 | 3876 | |
| 3843 | 3877 | zcu.sema_prog_node = main_progress_node.start("Semantic Analysis", 0); |
| ... | ... | @@ -4280,7 +4314,7 @@ fn workerDocsWasmFallible(comp: *Compilation, prog_node: std.Progress.Node) anye |
| 4280 | 4314 | }; |
| 4281 | 4315 | } |
| 4282 | 4316 | |
| 4283 | fn workerAstGenFile( | |
| 4317 | fn workerUpdateFile( | |
| 4284 | 4318 | tid: usize, |
| 4285 | 4319 | comp: *Compilation, |
| 4286 | 4320 | file: *Zcu.File, |
| ... | ... | @@ -4290,40 +4324,44 @@ fn workerAstGenFile( |
| 4290 | 4324 | wg: *WaitGroup, |
| 4291 | 4325 | src: Zcu.AstGenSrc, |
| 4292 | 4326 | ) void { |
| 4293 | assert(file.getMode() == .zig); | |
| 4294 | 4327 | const child_prog_node = prog_node.start(file.sub_file_path, 0); |
| 4295 | 4328 | defer child_prog_node.end(); |
| 4296 | 4329 | |
| 4297 | 4330 | const pt: Zcu.PerThread = .activate(comp.zcu.?, @enumFromInt(tid)); |
| 4298 | 4331 | defer pt.deactivate(); |
| 4299 | pt.astGenFile(file, path_digest) catch |err| switch (err) { | |
| 4332 | pt.updateFile(file, path_digest) catch |err| switch (err) { | |
| 4300 | 4333 | error.AnalysisFail => return, |
| 4301 | 4334 | else => { |
| 4302 | file.status = .retryable_failure; | |
| 4303 | 4335 | pt.reportRetryableAstGenError(src, file_index, err) catch |oom| switch (oom) { |
| 4304 | // Swallowing this error is OK because it's implied to be OOM when | |
| 4305 | // there is a missing `failed_files` error message. | |
| 4306 | error.OutOfMemory => {}, | |
| 4336 | error.OutOfMemory => { | |
| 4337 | comp.mutex.lock(); | |
| 4338 | defer comp.mutex.unlock(); | |
| 4339 | comp.setAllocFailure(); | |
| 4340 | }, | |
| 4307 | 4341 | }; |
| 4308 | 4342 | return; |
| 4309 | 4343 | }, |
| 4310 | 4344 | }; |
| 4311 | 4345 | |
| 4346 | switch (file.getMode()) { | |
| 4347 | .zig => {}, // continue to logic below | |
| 4348 | .zon => return, // ZON can't import anything so we're done | |
| 4349 | } | |
| 4350 | ||
| 4312 | 4351 | // Pre-emptively look for `@import` paths and queue them up. |
| 4313 | 4352 | // If we experience an error preemptively fetching the |
| 4314 | 4353 | // file, just ignore it and let it happen again later during Sema. |
| 4315 | assert(file.zir_loaded); | |
| 4316 | const imports_index = file.zir.extra[@intFromEnum(Zir.ExtraIndex.imports)]; | |
| 4354 | const imports_index = file.zir.?.extra[@intFromEnum(Zir.ExtraIndex.imports)]; | |
| 4317 | 4355 | if (imports_index != 0) { |
| 4318 | const extra = file.zir.extraData(Zir.Inst.Imports, imports_index); | |
| 4356 | const extra = file.zir.?.extraData(Zir.Inst.Imports, imports_index); | |
| 4319 | 4357 | var import_i: u32 = 0; |
| 4320 | 4358 | var extra_index = extra.end; |
| 4321 | 4359 | |
| 4322 | 4360 | while (import_i < extra.data.imports_len) : (import_i += 1) { |
| 4323 | const item = file.zir.extraData(Zir.Inst.Imports.Item, extra_index); | |
| 4361 | const item = file.zir.?.extraData(Zir.Inst.Imports.Item, extra_index); | |
| 4324 | 4362 | extra_index = item.end; |
| 4325 | 4363 | |
| 4326 | const import_path = file.zir.nullTerminatedString(item.data.name); | |
| 4364 | const import_path = file.zir.?.nullTerminatedString(item.data.name); | |
| 4327 | 4365 | // `@import("builtin")` is handled specially. |
| 4328 | 4366 | if (mem.eql(u8, import_path, "builtin")) continue; |
| 4329 | 4367 | |
| ... | ... | @@ -4344,7 +4382,7 @@ fn workerAstGenFile( |
| 4344 | 4382 | const imported_path_digest = pt.zcu.filePathDigest(res.file_index); |
| 4345 | 4383 | break :blk .{ res, imported_path_digest }; |
| 4346 | 4384 | }; |
| 4347 | if (import_result.is_new and import_result.file.getMode() == .zig) { | |
| 4385 | if (import_result.is_new) { | |
| 4348 | 4386 | log.debug("AstGen of {s} has import '{s}'; queuing AstGen of {s}", .{ |
| 4349 | 4387 | file.sub_file_path, import_path, import_result.file.sub_file_path, |
| 4350 | 4388 | }); |
| ... | ... | @@ -4352,7 +4390,7 @@ fn workerAstGenFile( |
| 4352 | 4390 | .importing_file = file_index, |
| 4353 | 4391 | .import_tok = item.data.token, |
| 4354 | 4392 | } }; |
| 4355 | comp.thread_pool.spawnWgId(wg, workerAstGenFile, .{ | |
| 4393 | comp.thread_pool.spawnWgId(wg, workerUpdateFile, .{ | |
| 4356 | 4394 | comp, import_result.file, import_result.file_index, imported_path_digest, prog_node, wg, sub_src, |
| 4357 | 4395 | }); |
| 4358 | 4396 | } |
| ... | ... | @@ -4375,7 +4413,7 @@ fn workerUpdateBuiltinZigFile( |
| 4375 | 4413 | }; |
| 4376 | 4414 | } |
| 4377 | 4415 | |
| 4378 | fn workerCheckEmbedFile(tid: usize, comp: *Compilation, ef_index: Zcu.EmbedFile.Index, ef: *Zcu.EmbedFile) void { | |
| 4416 | fn workerUpdateEmbedFile(tid: usize, comp: *Compilation, ef_index: Zcu.EmbedFile.Index, ef: *Zcu.EmbedFile) void { | |
| 4379 | 4417 | comp.detectEmbedFileUpdate(@enumFromInt(tid), ef_index, ef) catch |err| switch (err) { |
| 4380 | 4418 | error.OutOfMemory => { |
| 4381 | 4419 | comp.mutex.lock(); |
src/InternPool.zig+8-12| ... | ... | @@ -17,13 +17,6 @@ tid_shift_31: if (single_threaded) u0 else std.math.Log2Int(u32), |
| 17 | 17 | /// Cached shift amount to put a `tid` in the top bits of a 32-bit value. |
| 18 | 18 | tid_shift_32: if (single_threaded) u0 else std.math.Log2Int(u32), |
| 19 | 19 | |
| 20 | /// Dependencies on whether an entire file gets past AstGen. | |
| 21 | /// These are triggered by `@import`, so that: | |
| 22 | /// * if a file initially fails AstGen, triggering a transitive failure, when a future update | |
| 23 | /// causes it to succeed AstGen, the `@import` is re-analyzed, allowing analysis to proceed | |
| 24 | /// * if a file initially succeds AstGen, but a future update causes the file to fail it, | |
| 25 | /// the `@import` is re-analyzed, registering a transitive failure | |
| 26 | file_deps: std.AutoArrayHashMapUnmanaged(FileIndex, DepEntry.Index), | |
| 27 | 20 | /// Dependencies on the source code hash associated with a ZIR instruction. |
| 28 | 21 | /// * For a `declaration`, this is the entire declaration body. |
| 29 | 22 | /// * For a `struct_decl`, `union_decl`, etc, this is the source of the fields (but not declarations). |
| ... | ... | @@ -42,6 +35,9 @@ nav_ty_deps: std.AutoArrayHashMapUnmanaged(Nav.Index, DepEntry.Index), |
| 42 | 35 | /// * a container type requiring resolution (invalidated when the type must be recreated at a new index) |
| 43 | 36 | /// Value is index into `dep_entries` of the first dependency on this interned value. |
| 44 | 37 | interned_deps: std.AutoArrayHashMapUnmanaged(Index, DepEntry.Index), |
| 38 | /// Dependencies on a ZON file. Triggered by `@import` of ZON. | |
| 39 | /// Value is index into `dep_entries` of the first dependency on this ZON file. | |
| 40 | zon_file_deps: std.AutoArrayHashMapUnmanaged(FileIndex, DepEntry.Index), | |
| 45 | 41 | /// Dependencies on an embedded file. |
| 46 | 42 | /// Introduced by `@embedFile`; invalidated when the file changes. |
| 47 | 43 | /// Value is index into `dep_entries` of the first dependency on this `Zcu.EmbedFile`. |
| ... | ... | @@ -89,11 +85,11 @@ pub const empty: InternPool = .{ |
| 89 | 85 | .tid_shift_30 = if (single_threaded) 0 else 31, |
| 90 | 86 | .tid_shift_31 = if (single_threaded) 0 else 31, |
| 91 | 87 | .tid_shift_32 = if (single_threaded) 0 else 31, |
| 92 | .file_deps = .empty, | |
| 93 | 88 | .src_hash_deps = .empty, |
| 94 | 89 | .nav_val_deps = .empty, |
| 95 | 90 | .nav_ty_deps = .empty, |
| 96 | 91 | .interned_deps = .empty, |
| 92 | .zon_file_deps = .empty, | |
| 97 | 93 | .embed_file_deps = .empty, |
| 98 | 94 | .namespace_deps = .empty, |
| 99 | 95 | .namespace_name_deps = .empty, |
| ... | ... | @@ -824,11 +820,11 @@ pub const Nav = struct { |
| 824 | 820 | }; |
| 825 | 821 | |
| 826 | 822 | pub const Dependee = union(enum) { |
| 827 | file: FileIndex, | |
| 828 | 823 | src_hash: TrackedInst.Index, |
| 829 | 824 | nav_val: Nav.Index, |
| 830 | 825 | nav_ty: Nav.Index, |
| 831 | 826 | interned: Index, |
| 827 | zon_file: FileIndex, | |
| 832 | 828 | embed_file: Zcu.EmbedFile.Index, |
| 833 | 829 | namespace: TrackedInst.Index, |
| 834 | 830 | namespace_name: NamespaceNameKey, |
| ... | ... | @@ -876,11 +872,11 @@ pub const DependencyIterator = struct { |
| 876 | 872 | |
| 877 | 873 | pub fn dependencyIterator(ip: *const InternPool, dependee: Dependee) DependencyIterator { |
| 878 | 874 | const first_entry = switch (dependee) { |
| 879 | .file => |x| ip.file_deps.get(x), | |
| 880 | 875 | .src_hash => |x| ip.src_hash_deps.get(x), |
| 881 | 876 | .nav_val => |x| ip.nav_val_deps.get(x), |
| 882 | 877 | .nav_ty => |x| ip.nav_ty_deps.get(x), |
| 883 | 878 | .interned => |x| ip.interned_deps.get(x), |
| 879 | .zon_file => |x| ip.zon_file_deps.get(x), | |
| 884 | 880 | .embed_file => |x| ip.embed_file_deps.get(x), |
| 885 | 881 | .namespace => |x| ip.namespace_deps.get(x), |
| 886 | 882 | .namespace_name => |x| ip.namespace_name_deps.get(x), |
| ... | ... | @@ -947,11 +943,11 @@ pub fn addDependency(ip: *InternPool, gpa: Allocator, depender: AnalUnit, depend |
| 947 | 943 | }, |
| 948 | 944 | inline else => |dependee_payload, tag| new_index: { |
| 949 | 945 | const gop = try switch (tag) { |
| 950 | .file => ip.file_deps, | |
| 951 | 946 | .src_hash => ip.src_hash_deps, |
| 952 | 947 | .nav_val => ip.nav_val_deps, |
| 953 | 948 | .nav_ty => ip.nav_ty_deps, |
| 954 | 949 | .interned => ip.interned_deps, |
| 950 | .zon_file => ip.zon_file_deps, | |
| 955 | 951 | .embed_file => ip.embed_file_deps, |
| 956 | 952 | .namespace => ip.namespace_deps, |
| 957 | 953 | .namespace_name => ip.namespace_name_deps, |
| ... | ... | @@ -6688,11 +6684,11 @@ pub fn init(ip: *InternPool, gpa: Allocator, available_threads: usize) !void { |
| 6688 | 6684 | pub fn deinit(ip: *InternPool, gpa: Allocator) void { |
| 6689 | 6685 | if (debug_state.enable_checks) std.debug.assert(debug_state.intern_pool == null); |
| 6690 | 6686 | |
| 6691 | ip.file_deps.deinit(gpa); | |
| 6692 | 6687 | ip.src_hash_deps.deinit(gpa); |
| 6693 | 6688 | ip.nav_val_deps.deinit(gpa); |
| 6694 | 6689 | ip.nav_ty_deps.deinit(gpa); |
| 6695 | 6690 | ip.interned_deps.deinit(gpa); |
| 6691 | ip.zon_file_deps.deinit(gpa); | |
| 6696 | 6692 | ip.embed_file_deps.deinit(gpa); |
| 6697 | 6693 | ip.namespace_deps.deinit(gpa); |
| 6698 | 6694 | ip.namespace_name_deps.deinit(gpa); |
src/Package/Module.zig+4-7| ... | ... | @@ -482,15 +482,12 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Package.Module { |
| 482 | 482 | }; |
| 483 | 483 | new_file.* = .{ |
| 484 | 484 | .sub_file_path = "builtin.zig", |
| 485 | .source = generated_builtin_source, | |
| 486 | .source_loaded = true, | |
| 487 | .tree_loaded = false, | |
| 488 | .zir_loaded = false, | |
| 489 | 485 | .stat = undefined, |
| 490 | .tree = undefined, | |
| 491 | .zir = undefined, | |
| 486 | .source = generated_builtin_source, | |
| 487 | .tree = null, | |
| 488 | .zir = null, | |
| 489 | .zoir = null, | |
| 492 | 490 | .status = .never_loaded, |
| 493 | .prev_status = .never_loaded, | |
| 494 | 491 | .mod = new, |
| 495 | 492 | }; |
| 496 | 493 | break :b new; |
src/Sema.zig+8-16| ... | ... | @@ -6140,10 +6140,9 @@ fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileEr |
| 6140 | 6140 | return sema.fail(&child_block, src, "C import failed: {s}", .{@errorName(err)}); |
| 6141 | 6141 | |
| 6142 | 6142 | const path_digest = zcu.filePathDigest(result.file_index); |
| 6143 | pt.astGenFile(result.file, path_digest) catch |err| | |
| 6143 | pt.updateFile(result.file, path_digest) catch |err| | |
| 6144 | 6144 | return sema.fail(&child_block, src, "C import failed: {s}", .{@errorName(err)}); |
| 6145 | 6145 | |
| 6146 | try sema.declareDependency(.{ .file = result.file_index }); | |
| 6147 | 6146 | try pt.ensureFileAnalyzed(result.file_index); |
| 6148 | 6147 | const ty = zcu.fileRootType(result.file_index); |
| 6149 | 6148 | try sema.declareDependency(.{ .interned = ty }); |
| ... | ... | @@ -7649,9 +7648,8 @@ fn analyzeCall( |
| 7649 | 7648 | const nav = ip.getNav(info.owner_nav); |
| 7650 | 7649 | const resolved_func_inst = info.zir_body_inst.resolveFull(ip) orelse return error.AnalysisFail; |
| 7651 | 7650 | const file = zcu.fileByIndex(resolved_func_inst.file); |
| 7652 | assert(file.zir_loaded); | |
| 7653 | const zir_info = file.zir.getFnInfo(resolved_func_inst.inst); | |
| 7654 | break :b .{ nav, file.zir, info.zir_body_inst, resolved_func_inst.inst, zir_info }; | |
| 7651 | const zir_info = file.zir.?.getFnInfo(resolved_func_inst.inst); | |
| 7652 | break :b .{ nav, file.zir.?, info.zir_body_inst, resolved_func_inst.inst, zir_info }; | |
| 7655 | 7653 | } else .{ undefined, undefined, undefined, undefined, undefined }; |
| 7656 | 7654 | |
| 7657 | 7655 | // This is the `inst_map` used when evaluating generic parameters and return types. |
| ... | ... | @@ -13987,7 +13985,6 @@ fn zirImport(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. |
| 13987 | 13985 | }; |
| 13988 | 13986 | switch (result.file.getMode()) { |
| 13989 | 13987 | .zig => { |
| 13990 | try sema.declareDependency(.{ .file = result.file_index }); | |
| 13991 | 13988 | try pt.ensureFileAnalyzed(result.file_index); |
| 13992 | 13989 | const ty = zcu.fileRootType(result.file_index); |
| 13993 | 13990 | try sema.declareDependency(.{ .interned = ty }); |
| ... | ... | @@ -13995,12 +13992,6 @@ fn zirImport(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. |
| 13995 | 13992 | return Air.internedToRef(ty); |
| 13996 | 13993 | }, |
| 13997 | 13994 | .zon => { |
| 13998 | _ = result.file.getTree(zcu.gpa) catch |err| { | |
| 13999 | // TODO: these errors are file system errors; make sure an update() will | |
| 14000 | // retry this and not cache the file system error, which may be transient. | |
| 14001 | return sema.fail(block, operand_src, "unable to open '{s}': {s}", .{ result.file.sub_file_path, @errorName(err) }); | |
| 14002 | }; | |
| 14003 | ||
| 14004 | 13995 | if (extra.res_ty == .none) { |
| 14005 | 13996 | return sema.fail(block, operand_src, "'@import' of ZON must have a known result type", .{}); |
| 14006 | 13997 | } |
| ... | ... | @@ -14010,6 +14001,7 @@ fn zirImport(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. |
| 14010 | 14001 | return sema.fail(block, operand_src, "'@import' of ZON must have a known result type", .{}); |
| 14011 | 14002 | } |
| 14012 | 14003 | |
| 14004 | try sema.declareDependency(.{ .zon_file = result.file_index }); | |
| 14013 | 14005 | const interned = try LowerZon.run( |
| 14014 | 14006 | sema, |
| 14015 | 14007 | result.file, |
| ... | ... | @@ -35328,7 +35320,7 @@ fn backingIntType( |
| 35328 | 35320 | break :blk accumulator; |
| 35329 | 35321 | }; |
| 35330 | 35322 | |
| 35331 | const zir = zcu.namespacePtr(struct_type.namespace).fileScope(zcu).zir; | |
| 35323 | const zir = zcu.namespacePtr(struct_type.namespace).fileScope(zcu).zir.?; | |
| 35332 | 35324 | const zir_index = struct_type.zir_index.resolve(ip) orelse return error.AnalysisFail; |
| 35333 | 35325 | const extended = zir.instructions.items(.data)[@intFromEnum(zir_index)].extended; |
| 35334 | 35326 | assert(extended.opcode == .struct_decl); |
| ... | ... | @@ -35948,7 +35940,7 @@ fn structFields( |
| 35948 | 35940 | const gpa = zcu.gpa; |
| 35949 | 35941 | const ip = &zcu.intern_pool; |
| 35950 | 35942 | const namespace_index = struct_type.namespace; |
| 35951 | const zir = zcu.namespacePtr(namespace_index).fileScope(zcu).zir; | |
| 35943 | const zir = zcu.namespacePtr(namespace_index).fileScope(zcu).zir.?; | |
| 35952 | 35944 | const zir_index = struct_type.zir_index.resolve(ip) orelse return error.AnalysisFail; |
| 35953 | 35945 | |
| 35954 | 35946 | const fields_len, _, var extra_index = structZirInfo(zir, zir_index); |
| ... | ... | @@ -36149,7 +36141,7 @@ fn structFieldInits( |
| 36149 | 36141 | assert(!struct_type.haveFieldInits(ip)); |
| 36150 | 36142 | |
| 36151 | 36143 | const namespace_index = struct_type.namespace; |
| 36152 | const zir = zcu.namespacePtr(namespace_index).fileScope(zcu).zir; | |
| 36144 | const zir = zcu.namespacePtr(namespace_index).fileScope(zcu).zir.?; | |
| 36153 | 36145 | const zir_index = struct_type.zir_index.resolve(ip) orelse return error.AnalysisFail; |
| 36154 | 36146 | const fields_len, _, var extra_index = structZirInfo(zir, zir_index); |
| 36155 | 36147 | |
| ... | ... | @@ -36268,7 +36260,7 @@ fn unionFields( |
| 36268 | 36260 | const zcu = pt.zcu; |
| 36269 | 36261 | const gpa = zcu.gpa; |
| 36270 | 36262 | const ip = &zcu.intern_pool; |
| 36271 | const zir = zcu.namespacePtr(union_type.namespace).fileScope(zcu).zir; | |
| 36263 | const zir = zcu.namespacePtr(union_type.namespace).fileScope(zcu).zir.?; | |
| 36272 | 36264 | const zir_index = union_type.zir_index.resolve(ip) orelse return error.AnalysisFail; |
| 36273 | 36265 | const extended = zir.instructions.items(.data)[@intFromEnum(zir_index)].extended; |
| 36274 | 36266 | assert(extended.opcode == .union_decl); |
src/Sema/LowerZon.zig-2| ... | ... | @@ -39,8 +39,6 @@ pub fn run( |
| 39 | 39 | ) CompileError!InternPool.Index { |
| 40 | 40 | const pt = sema.pt; |
| 41 | 41 | |
| 42 | _ = try file.getZoir(pt.zcu); | |
| 43 | ||
| 44 | 42 | const tracked_inst = try pt.zcu.intern_pool.trackZir(pt.zcu.gpa, pt.tid, .{ |
| 45 | 43 | .file = file_index, |
| 46 | 44 | .inst = .main_struct_inst, // this is the only trackable instruction in a ZON file |
src/Type.zig+3-4| ... | ... | @@ -3587,8 +3587,7 @@ pub fn typeDeclSrcLine(ty: Type, zcu: *Zcu) ?u32 { |
| 3587 | 3587 | }; |
| 3588 | 3588 | const info = tracked.resolveFull(&zcu.intern_pool) orelse return null; |
| 3589 | 3589 | const file = zcu.fileByIndex(info.file); |
| 3590 | assert(file.zir_loaded); | |
| 3591 | const zir = file.zir; | |
| 3590 | const zir = file.zir.?; | |
| 3592 | 3591 | const inst = zir.instructions.get(@intFromEnum(info.inst)); |
| 3593 | 3592 | return switch (inst.tag) { |
| 3594 | 3593 | .struct_init, .struct_init_ref => zir.extraData(Zir.Inst.StructInit, inst.data.pl_node.payload_index).data.abs_line, |
| ... | ... | @@ -3905,7 +3904,7 @@ fn resolveStructInner( |
| 3905 | 3904 | var comptime_err_ret_trace = std.ArrayList(Zcu.LazySrcLoc).init(gpa); |
| 3906 | 3905 | defer comptime_err_ret_trace.deinit(); |
| 3907 | 3906 | |
| 3908 | const zir = zcu.namespacePtr(struct_obj.namespace).fileScope(zcu).zir; | |
| 3907 | const zir = zcu.namespacePtr(struct_obj.namespace).fileScope(zcu).zir.?; | |
| 3909 | 3908 | var sema: Sema = .{ |
| 3910 | 3909 | .pt = pt, |
| 3911 | 3910 | .gpa = gpa, |
| ... | ... | @@ -3959,7 +3958,7 @@ fn resolveUnionInner( |
| 3959 | 3958 | var comptime_err_ret_trace = std.ArrayList(Zcu.LazySrcLoc).init(gpa); |
| 3960 | 3959 | defer comptime_err_ret_trace.deinit(); |
| 3961 | 3960 | |
| 3962 | const zir = zcu.namespacePtr(union_obj.namespace).fileScope(zcu).zir; | |
| 3961 | const zir = zcu.namespacePtr(union_obj.namespace).fileScope(zcu).zir.?; | |
| 3963 | 3962 | var sema: Sema = .{ |
| 3964 | 3963 | .pt = pt, |
| 3965 | 3964 | .gpa = gpa, |
src/Zcu.zig+262-90| ... | ... | @@ -658,24 +658,35 @@ pub const Namespace = struct { |
| 658 | 658 | }; |
| 659 | 659 | |
| 660 | 660 | pub const File = struct { |
| 661 | status: Status, | |
| 662 | prev_status: Status, | |
| 663 | source_loaded: bool, | |
| 664 | tree_loaded: bool, | |
| 665 | zir_loaded: bool, | |
| 666 | 661 | /// Relative to the owning package's root source directory. |
| 667 | 662 | /// Memory is stored in gpa, owned by File. |
| 668 | 663 | sub_file_path: []const u8, |
| 669 | /// Whether this is populated depends on `source_loaded`. | |
| 670 | source: [:0]const u8, | |
| 664 | ||
| 665 | status: enum { | |
| 666 | /// We have not yet attempted to load this file. | |
| 667 | /// `stat` is not populated and may be `undefined`. | |
| 668 | never_loaded, | |
| 669 | /// A filesystem access failed. It should be retried on the next update. | |
| 670 | /// There is a `failed_files` entry containing a non-`null` message. | |
| 671 | /// `stat` is not populated and may be `undefined`. | |
| 672 | retryable_failure, | |
| 673 | /// Parsing/AstGen/ZonGen of this file has failed. | |
| 674 | /// There is an error in `zir` or `zoir`. | |
| 675 | /// There is a `failed_files` entry (with a `null` message). | |
| 676 | /// `stat` is populated. | |
| 677 | astgen_failure, | |
| 678 | /// Parsing and AstGen/ZonGen of this file has succeeded. | |
| 679 | /// `stat` is populated. | |
| 680 | success, | |
| 681 | }, | |
| 671 | 682 | /// Whether this is populated depends on `status`. |
| 672 | 683 | stat: Cache.File.Stat, |
| 673 | /// Whether this is populated or not depends on `tree_loaded`. | |
| 674 | tree: Ast, | |
| 675 | /// Whether this is populated or not depends on `zir_loaded`. | |
| 676 | zir: Zir, | |
| 677 | /// Cached Zoir, generated lazily. | |
| 678 | zoir: ?Zoir = null, | |
| 684 | ||
| 685 | source: ?[:0]const u8, | |
| 686 | tree: ?Ast, | |
| 687 | zir: ?Zir, | |
| 688 | zoir: ?Zoir, | |
| 689 | ||
| 679 | 690 | /// Module that this file is a part of, managed externally. |
| 680 | 691 | mod: *Package.Module, |
| 681 | 692 | /// Whether this file is a part of multiple packages. This is an error condition which will be reported after AstGen. |
| ... | ... | @@ -683,19 +694,24 @@ pub const File = struct { |
| 683 | 694 | /// List of references to this file, used for multi-package errors. |
| 684 | 695 | references: std.ArrayListUnmanaged(File.Reference) = .empty, |
| 685 | 696 | |
| 686 | /// The most recent successful ZIR for this file, with no errors. | |
| 687 | /// This is only populated when a previously successful ZIR | |
| 688 | /// newly introduces compile errors during an update. When ZIR is | |
| 689 | /// successful, this field is unloaded. | |
| 697 | /// The ZIR for this file from the last update with no file failures. As such, this ZIR is never | |
| 698 | /// failed (although it may have compile errors). | |
| 699 | /// | |
| 700 | /// Because updates with file failures do not perform ZIR mapping or semantic analysis, we keep | |
| 701 | /// this around so we have the "old" ZIR to map when an update is ready to do so. Once such an | |
| 702 | /// update occurs, this field is unloaded, since it is no longer necessary. | |
| 703 | /// | |
| 704 | /// In other words, if `TrackedInst`s are tied to ZIR other than what's in the `zir` field, this | |
| 705 | /// field is populated with that old ZIR. | |
| 690 | 706 | prev_zir: ?*Zir = null, |
| 691 | 707 | |
| 692 | pub const Status = enum { | |
| 693 | never_loaded, | |
| 694 | retryable_failure, | |
| 695 | parse_failure, | |
| 696 | astgen_failure, | |
| 697 | success_zir, | |
| 698 | }; | |
| 708 | /// This field serves a similar purpose to `prev_zir`, but for ZOIR. However, since we do not | |
| 709 | /// need to map old ZOIR to new ZOIR -- instead only invalidating dependencies if the ZOIR | |
| 710 | /// changed -- this field is just a simple boolean. | |
| 711 | /// | |
| 712 | /// When `zoir` is updated, this field is set to `true`. In `updateZirRefs`, if this is `true`, | |
| 713 | /// we invalidate the corresponding `zon_file` dependency, and reset it to `false`. | |
| 714 | zoir_invalidated: bool = false, | |
| 699 | 715 | |
| 700 | 716 | /// A single reference to a file. |
| 701 | 717 | pub const Reference = union(enum) { |
| ... | ... | @@ -727,23 +743,23 @@ pub const File = struct { |
| 727 | 743 | } |
| 728 | 744 | |
| 729 | 745 | pub fn unloadTree(file: *File, gpa: Allocator) void { |
| 730 | if (file.tree_loaded) { | |
| 731 | file.tree_loaded = false; | |
| 732 | file.tree.deinit(gpa); | |
| 746 | if (file.tree) |*tree| { | |
| 747 | tree.deinit(gpa); | |
| 748 | file.tree = null; | |
| 733 | 749 | } |
| 734 | 750 | } |
| 735 | 751 | |
| 736 | 752 | pub fn unloadSource(file: *File, gpa: Allocator) void { |
| 737 | if (file.source_loaded) { | |
| 738 | file.source_loaded = false; | |
| 739 | gpa.free(file.source); | |
| 753 | if (file.source) |source| { | |
| 754 | gpa.free(source); | |
| 755 | file.source = null; | |
| 740 | 756 | } |
| 741 | 757 | } |
| 742 | 758 | |
| 743 | 759 | pub fn unloadZir(file: *File, gpa: Allocator) void { |
| 744 | if (file.zir_loaded) { | |
| 745 | file.zir_loaded = false; | |
| 746 | file.zir.deinit(gpa); | |
| 760 | if (file.zir) |*zir| { | |
| 761 | zir.deinit(gpa); | |
| 762 | file.zir = null; | |
| 747 | 763 | } |
| 748 | 764 | } |
| 749 | 765 | |
| ... | ... | @@ -753,8 +769,8 @@ pub const File = struct { |
| 753 | 769 | }; |
| 754 | 770 | |
| 755 | 771 | pub fn getSource(file: *File, gpa: Allocator) !Source { |
| 756 | if (file.source_loaded) return Source{ | |
| 757 | .bytes = file.source, | |
| 772 | if (file.source) |source| return .{ | |
| 773 | .bytes = source, | |
| 758 | 774 | .stat = file.stat, |
| 759 | 775 | }; |
| 760 | 776 | |
| ... | ... | @@ -769,18 +785,20 @@ pub const File = struct { |
| 769 | 785 | return error.FileTooBig; |
| 770 | 786 | |
| 771 | 787 | const source = try gpa.allocSentinel(u8, @as(usize, @intCast(stat.size)), 0); |
| 772 | defer if (!file.source_loaded) gpa.free(source); | |
| 788 | errdefer gpa.free(source); | |
| 789 | ||
| 773 | 790 | const amt = try f.readAll(source); |
| 774 | 791 | if (amt != stat.size) |
| 775 | 792 | return error.UnexpectedEndOfFile; |
| 776 | 793 | |
| 777 | 794 | // Here we do not modify stat fields because this function is the one |
| 778 | 795 | // used for error reporting. We need to keep the stat fields stale so that |
| 779 | // astGenFile can know to regenerate ZIR. | |
| 796 | // updateFile can know to regenerate ZIR. | |
| 780 | 797 | |
| 781 | 798 | file.source = source; |
| 782 | file.source_loaded = true; | |
| 783 | return Source{ | |
| 799 | errdefer comptime unreachable; // don't error after populating `source` | |
| 800 | ||
| 801 | return .{ | |
| 784 | 802 | .bytes = source, |
| 785 | 803 | .stat = .{ |
| 786 | 804 | .size = stat.size, |
| ... | ... | @@ -791,20 +809,20 @@ pub const File = struct { |
| 791 | 809 | } |
| 792 | 810 | |
| 793 | 811 | pub fn getTree(file: *File, gpa: Allocator) !*const Ast { |
| 794 | if (file.tree_loaded) return &file.tree; | |
| 812 | if (file.tree) |*tree| return tree; | |
| 795 | 813 | |
| 796 | 814 | const source = try file.getSource(gpa); |
| 797 | file.tree = try Ast.parse(gpa, source.bytes, file.getMode()); | |
| 798 | file.tree_loaded = true; | |
| 799 | return &file.tree; | |
| 815 | file.tree = try .parse(gpa, source.bytes, file.getMode()); | |
| 816 | return &file.tree.?; | |
| 800 | 817 | } |
| 801 | 818 | |
| 802 | 819 | pub fn getZoir(file: *File, zcu: *Zcu) !*const Zoir { |
| 803 | 820 | if (file.zoir) |*zoir| return zoir; |
| 804 | 821 | |
| 805 | assert(file.tree_loaded); | |
| 806 | assert(file.tree.mode == .zon); | |
| 807 | file.zoir = try ZonGen.generate(zcu.gpa, file.tree, .{}); | |
| 822 | const tree = file.tree.?; | |
| 823 | assert(tree.mode == .zon); | |
| 824 | ||
| 825 | file.zoir = try ZonGen.generate(zcu.gpa, tree, .{}); | |
| 808 | 826 | if (file.zoir.?.hasCompileErrors()) { |
| 809 | 827 | try zcu.failed_files.putNoClobber(zcu.gpa, file, null); |
| 810 | 828 | return error.AnalysisFail; |
| ... | ... | @@ -854,13 +872,6 @@ pub const File = struct { |
| 854 | 872 | std.debug.print("{s}:{d}:{d}\n", .{ file.sub_file_path, loc.line + 1, loc.column + 1 }); |
| 855 | 873 | } |
| 856 | 874 | |
| 857 | pub fn okToReportErrors(file: File) bool { | |
| 858 | return switch (file.status) { | |
| 859 | .parse_failure, .astgen_failure => false, | |
| 860 | else => true, | |
| 861 | }; | |
| 862 | } | |
| 863 | ||
| 864 | 875 | /// Add a reference to this file during AstGen. |
| 865 | 876 | pub fn addReference(file: *File, zcu: *Zcu, ref: File.Reference) !void { |
| 866 | 877 | // Don't add the same module root twice. Note that since we always add module roots at the |
| ... | ... | @@ -900,18 +911,18 @@ pub const File = struct { |
| 900 | 911 | |
| 901 | 912 | // We can only mark children as failed if the ZIR is loaded, which may not |
| 902 | 913 | // be the case if there were other astgen failures in this file |
| 903 | if (!file.zir_loaded) return; | |
| 914 | if (file.zir == null) return; | |
| 904 | 915 | |
| 905 | const imports_index = file.zir.extra[@intFromEnum(Zir.ExtraIndex.imports)]; | |
| 916 | const imports_index = file.zir.?.extra[@intFromEnum(Zir.ExtraIndex.imports)]; | |
| 906 | 917 | if (imports_index == 0) return; |
| 907 | const extra = file.zir.extraData(Zir.Inst.Imports, imports_index); | |
| 918 | const extra = file.zir.?.extraData(Zir.Inst.Imports, imports_index); | |
| 908 | 919 | |
| 909 | 920 | var extra_index = extra.end; |
| 910 | 921 | for (0..extra.data.imports_len) |_| { |
| 911 | const item = file.zir.extraData(Zir.Inst.Imports.Item, extra_index); | |
| 922 | const item = file.zir.?.extraData(Zir.Inst.Imports.Item, extra_index); | |
| 912 | 923 | extra_index = item.end; |
| 913 | 924 | |
| 914 | const import_path = file.zir.nullTerminatedString(item.data.name); | |
| 925 | const import_path = file.zir.?.nullTerminatedString(item.data.name); | |
| 915 | 926 | if (mem.eql(u8, import_path, "builtin")) continue; |
| 916 | 927 | |
| 917 | 928 | const res = pt.importFile(file, import_path) catch continue; |
| ... | ... | @@ -1012,7 +1023,7 @@ pub const SrcLoc = struct { |
| 1012 | 1023 | lazy: LazySrcLoc.Offset, |
| 1013 | 1024 | |
| 1014 | 1025 | pub fn baseSrcToken(src_loc: SrcLoc) Ast.TokenIndex { |
| 1015 | const tree = src_loc.file_scope.tree; | |
| 1026 | const tree = src_loc.file_scope.tree.?; | |
| 1016 | 1027 | return tree.firstToken(src_loc.base_node); |
| 1017 | 1028 | } |
| 1018 | 1029 | |
| ... | ... | @@ -1057,7 +1068,6 @@ pub const SrcLoc = struct { |
| 1057 | 1068 | const node_off = traced_off.x; |
| 1058 | 1069 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1059 | 1070 | const node = src_loc.relativeToNodeIndex(node_off); |
| 1060 | assert(src_loc.file_scope.tree_loaded); | |
| 1061 | 1071 | return tree.nodeToSpan(node); |
| 1062 | 1072 | }, |
| 1063 | 1073 | .node_offset_main_token => |node_off| { |
| ... | ... | @@ -1069,7 +1079,6 @@ pub const SrcLoc = struct { |
| 1069 | 1079 | .node_offset_bin_op => |node_off| { |
| 1070 | 1080 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1071 | 1081 | const node = src_loc.relativeToNodeIndex(node_off); |
| 1072 | assert(src_loc.file_scope.tree_loaded); | |
| 1073 | 1082 | return tree.nodeToSpan(node); |
| 1074 | 1083 | }, |
| 1075 | 1084 | .node_offset_initializer => |node_off| { |
| ... | ... | @@ -2408,9 +2417,8 @@ pub const LazySrcLoc = struct { |
| 2408 | 2417 | if (zir_inst == .main_struct_inst) return .{ file, 0 }; |
| 2409 | 2418 | |
| 2410 | 2419 | // Otherwise, make sure ZIR is loaded. |
| 2411 | assert(file.zir_loaded); | |
| 2420 | const zir = file.zir.?; | |
| 2412 | 2421 | |
| 2413 | const zir = file.zir; | |
| 2414 | 2422 | const inst = zir.instructions.get(@intFromEnum(zir_inst)); |
| 2415 | 2423 | const base_node: Ast.Node.Index = switch (inst.tag) { |
| 2416 | 2424 | .declaration => inst.data.declaration.src_node, |
| ... | ... | @@ -2643,6 +2651,189 @@ pub fn loadZirCacheBody(gpa: Allocator, header: Zir.Header, cache_file: std.fs.F |
| 2643 | 2651 | return zir; |
| 2644 | 2652 | } |
| 2645 | 2653 | |
| 2654 | pub fn saveZirCache(gpa: Allocator, cache_file: std.fs.File, stat: std.fs.File.Stat, zir: Zir) (std.fs.File.WriteError || Allocator.Error)!void { | |
| 2655 | const safety_buffer = if (data_has_safety_tag) | |
| 2656 | try gpa.alloc([8]u8, zir.instructions.len) | |
| 2657 | else | |
| 2658 | undefined; | |
| 2659 | defer if (data_has_safety_tag) gpa.free(safety_buffer); | |
| 2660 | ||
| 2661 | const data_ptr: [*]const u8 = if (data_has_safety_tag) | |
| 2662 | if (zir.instructions.len == 0) | |
| 2663 | undefined | |
| 2664 | else | |
| 2665 | @ptrCast(safety_buffer.ptr) | |
| 2666 | else | |
| 2667 | @ptrCast(zir.instructions.items(.data).ptr); | |
| 2668 | ||
| 2669 | if (data_has_safety_tag) { | |
| 2670 | // The `Data` union has a safety tag but in the file format we store it without. | |
| 2671 | for (zir.instructions.items(.data), 0..) |*data, i| { | |
| 2672 | const as_struct: *const HackDataLayout = @ptrCast(data); | |
| 2673 | safety_buffer[i] = as_struct.data; | |
| 2674 | } | |
| 2675 | } | |
| 2676 | ||
| 2677 | const header: Zir.Header = .{ | |
| 2678 | .instructions_len = @intCast(zir.instructions.len), | |
| 2679 | .string_bytes_len = @intCast(zir.string_bytes.len), | |
| 2680 | .extra_len = @intCast(zir.extra.len), | |
| 2681 | ||
| 2682 | .stat_size = stat.size, | |
| 2683 | .stat_inode = stat.inode, | |
| 2684 | .stat_mtime = stat.mtime, | |
| 2685 | }; | |
| 2686 | var iovecs: [5]std.posix.iovec_const = .{ | |
| 2687 | .{ | |
| 2688 | .base = @ptrCast(&header), | |
| 2689 | .len = @sizeOf(Zir.Header), | |
| 2690 | }, | |
| 2691 | .{ | |
| 2692 | .base = @ptrCast(zir.instructions.items(.tag).ptr), | |
| 2693 | .len = zir.instructions.len, | |
| 2694 | }, | |
| 2695 | .{ | |
| 2696 | .base = data_ptr, | |
| 2697 | .len = zir.instructions.len * 8, | |
| 2698 | }, | |
| 2699 | .{ | |
| 2700 | .base = zir.string_bytes.ptr, | |
| 2701 | .len = zir.string_bytes.len, | |
| 2702 | }, | |
| 2703 | .{ | |
| 2704 | .base = @ptrCast(zir.extra.ptr), | |
| 2705 | .len = zir.extra.len * 4, | |
| 2706 | }, | |
| 2707 | }; | |
| 2708 | try cache_file.writevAll(&iovecs); | |
| 2709 | } | |
| 2710 | ||
| 2711 | pub fn saveZoirCache(cache_file: std.fs.File, stat: std.fs.File.Stat, zoir: Zoir) std.fs.File.WriteError!void { | |
| 2712 | const header: Zoir.Header = .{ | |
| 2713 | .nodes_len = @intCast(zoir.nodes.len), | |
| 2714 | .extra_len = @intCast(zoir.extra.len), | |
| 2715 | .limbs_len = @intCast(zoir.limbs.len), | |
| 2716 | .string_bytes_len = @intCast(zoir.string_bytes.len), | |
| 2717 | .compile_errors_len = @intCast(zoir.compile_errors.len), | |
| 2718 | .error_notes_len = @intCast(zoir.error_notes.len), | |
| 2719 | ||
| 2720 | .stat_size = stat.size, | |
| 2721 | .stat_inode = stat.inode, | |
| 2722 | .stat_mtime = stat.mtime, | |
| 2723 | }; | |
| 2724 | var iovecs: [9]std.posix.iovec_const = .{ | |
| 2725 | .{ | |
| 2726 | .base = @ptrCast(&header), | |
| 2727 | .len = @sizeOf(Zoir.Header), | |
| 2728 | }, | |
| 2729 | .{ | |
| 2730 | .base = @ptrCast(zoir.nodes.items(.tag)), | |
| 2731 | .len = zoir.nodes.len * @sizeOf(Zoir.Node.Repr.Tag), | |
| 2732 | }, | |
| 2733 | .{ | |
| 2734 | .base = @ptrCast(zoir.nodes.items(.data)), | |
| 2735 | .len = zoir.nodes.len * 4, | |
| 2736 | }, | |
| 2737 | .{ | |
| 2738 | .base = @ptrCast(zoir.nodes.items(.ast_node)), | |
| 2739 | .len = zoir.nodes.len * 4, | |
| 2740 | }, | |
| 2741 | .{ | |
| 2742 | .base = @ptrCast(zoir.extra), | |
| 2743 | .len = zoir.extra.len * 4, | |
| 2744 | }, | |
| 2745 | .{ | |
| 2746 | .base = @ptrCast(zoir.limbs), | |
| 2747 | .len = zoir.limbs.len * 4, | |
| 2748 | }, | |
| 2749 | .{ | |
| 2750 | .base = zoir.string_bytes.ptr, | |
| 2751 | .len = zoir.string_bytes.len, | |
| 2752 | }, | |
| 2753 | .{ | |
| 2754 | .base = @ptrCast(zoir.compile_errors), | |
| 2755 | .len = zoir.compile_errors.len * @sizeOf(Zoir.CompileError), | |
| 2756 | }, | |
| 2757 | .{ | |
| 2758 | .base = @ptrCast(zoir.error_notes), | |
| 2759 | .len = zoir.error_notes.len * @sizeOf(Zoir.CompileError.Note), | |
| 2760 | }, | |
| 2761 | }; | |
| 2762 | try cache_file.writevAll(&iovecs); | |
| 2763 | } | |
| 2764 | ||
| 2765 | pub fn loadZoirCacheBody(gpa: Allocator, header: Zoir.Header, cache_file: std.fs.File) !Zoir { | |
| 2766 | var zoir: Zoir = .{ | |
| 2767 | .nodes = .empty, | |
| 2768 | .extra = &.{}, | |
| 2769 | .limbs = &.{}, | |
| 2770 | .string_bytes = &.{}, | |
| 2771 | .compile_errors = &.{}, | |
| 2772 | .error_notes = &.{}, | |
| 2773 | }; | |
| 2774 | errdefer zoir.deinit(gpa); | |
| 2775 | ||
| 2776 | zoir.nodes = nodes: { | |
| 2777 | var nodes: std.MultiArrayList(Zoir.Node.Repr) = .empty; | |
| 2778 | defer nodes.deinit(gpa); | |
| 2779 | try nodes.setCapacity(gpa, header.nodes_len); | |
| 2780 | nodes.len = header.nodes_len; | |
| 2781 | break :nodes nodes.toOwnedSlice(); | |
| 2782 | }; | |
| 2783 | ||
| 2784 | zoir.extra = try gpa.alloc(u32, header.extra_len); | |
| 2785 | zoir.limbs = try gpa.alloc(std.math.big.Limb, header.limbs_len); | |
| 2786 | zoir.string_bytes = try gpa.alloc(u8, header.string_bytes_len); | |
| 2787 | ||
| 2788 | zoir.compile_errors = try gpa.alloc(Zoir.CompileError, header.compile_errors_len); | |
| 2789 | zoir.error_notes = try gpa.alloc(Zoir.CompileError.Note, header.error_notes_len); | |
| 2790 | ||
| 2791 | var iovecs: [8]std.posix.iovec = .{ | |
| 2792 | .{ | |
| 2793 | .base = @ptrCast(zoir.nodes.items(.tag)), | |
| 2794 | .len = header.nodes_len * @sizeOf(Zoir.Node.Repr.Tag), | |
| 2795 | }, | |
| 2796 | .{ | |
| 2797 | .base = @ptrCast(zoir.nodes.items(.data)), | |
| 2798 | .len = header.nodes_len * 4, | |
| 2799 | }, | |
| 2800 | .{ | |
| 2801 | .base = @ptrCast(zoir.nodes.items(.ast_node)), | |
| 2802 | .len = header.nodes_len * 4, | |
| 2803 | }, | |
| 2804 | .{ | |
| 2805 | .base = @ptrCast(zoir.extra), | |
| 2806 | .len = header.extra_len * 4, | |
| 2807 | }, | |
| 2808 | .{ | |
| 2809 | .base = @ptrCast(zoir.limbs), | |
| 2810 | .len = header.limbs_len * @sizeOf(std.math.big.Limb), | |
| 2811 | }, | |
| 2812 | .{ | |
| 2813 | .base = zoir.string_bytes.ptr, | |
| 2814 | .len = header.string_bytes_len, | |
| 2815 | }, | |
| 2816 | .{ | |
| 2817 | .base = @ptrCast(zoir.compile_errors), | |
| 2818 | .len = header.compile_errors_len * @sizeOf(Zoir.CompileError), | |
| 2819 | }, | |
| 2820 | .{ | |
| 2821 | .base = @ptrCast(zoir.error_notes), | |
| 2822 | .len = header.error_notes_len * @sizeOf(Zoir.CompileError.Note), | |
| 2823 | }, | |
| 2824 | }; | |
| 2825 | ||
| 2826 | const bytes_expected = expected: { | |
| 2827 | var n: usize = 0; | |
| 2828 | for (iovecs) |v| n += v.len; | |
| 2829 | break :expected n; | |
| 2830 | }; | |
| 2831 | ||
| 2832 | const bytes_read = try cache_file.readvAll(&iovecs); | |
| 2833 | if (bytes_read != bytes_expected) return error.UnexpectedFileSize; | |
| 2834 | return zoir; | |
| 2835 | } | |
| 2836 | ||
| 2646 | 2837 | pub fn markDependeeOutdated( |
| 2647 | 2838 | zcu: *Zcu, |
| 2648 | 2839 | /// When we are diffing ZIR and marking things as outdated, we won't yet have marked the dependencies as PO. |
| ... | ... | @@ -3303,19 +3494,6 @@ pub fn optimizeMode(zcu: *const Zcu) std.builtin.OptimizeMode { |
| 3303 | 3494 | return zcu.root_mod.optimize_mode; |
| 3304 | 3495 | } |
| 3305 | 3496 | |
| 3306 | fn lockAndClearFileCompileError(zcu: *Zcu, file: *File) void { | |
| 3307 | switch (file.status) { | |
| 3308 | .success_zir, .retryable_failure => {}, | |
| 3309 | .never_loaded, .parse_failure, .astgen_failure => { | |
| 3310 | zcu.comp.mutex.lock(); | |
| 3311 | defer zcu.comp.mutex.unlock(); | |
| 3312 | if (zcu.failed_files.fetchSwapRemove(file)) |kv| { | |
| 3313 | if (kv.value) |msg| msg.destroy(zcu.gpa); // Delete previous error message. | |
| 3314 | } | |
| 3315 | }, | |
| 3316 | } | |
| 3317 | } | |
| 3318 | ||
| 3319 | 3497 | pub fn handleUpdateExports( |
| 3320 | 3498 | zcu: *Zcu, |
| 3321 | 3499 | export_indices: []const Export.Index, |
| ... | ... | @@ -3670,9 +3848,7 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv |
| 3670 | 3848 | // `test` declarations are analyzed depending on the test filter. |
| 3671 | 3849 | const inst_info = nav.analysis.?.zir_index.resolveFull(ip) orelse continue; |
| 3672 | 3850 | const file = zcu.fileByIndex(inst_info.file); |
| 3673 | // If the file failed AstGen, the TrackedInst refers to the old ZIR. | |
| 3674 | const zir = if (file.status == .success_zir) file.zir else file.prev_zir.?.*; | |
| 3675 | const decl = zir.getDeclaration(inst_info.inst); | |
| 3851 | const decl = file.zir.?.getDeclaration(inst_info.inst); | |
| 3676 | 3852 | |
| 3677 | 3853 | if (!comp.config.is_test or file.mod != zcu.main_mod) continue; |
| 3678 | 3854 | |
| ... | ... | @@ -3702,9 +3878,7 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv |
| 3702 | 3878 | // These are named declarations. They are analyzed only if marked `export`. |
| 3703 | 3879 | const inst_info = ip.getNav(nav).analysis.?.zir_index.resolveFull(ip) orelse continue; |
| 3704 | 3880 | const file = zcu.fileByIndex(inst_info.file); |
| 3705 | // If the file failed AstGen, the TrackedInst refers to the old ZIR. | |
| 3706 | const zir = if (file.status == .success_zir) file.zir else file.prev_zir.?.*; | |
| 3707 | const decl = zir.getDeclaration(inst_info.inst); | |
| 3881 | const decl = file.zir.?.getDeclaration(inst_info.inst); | |
| 3708 | 3882 | if (decl.linkage == .@"export") { |
| 3709 | 3883 | const unit: AnalUnit = .wrap(.{ .nav_val = nav }); |
| 3710 | 3884 | if (!result.contains(unit)) { |
| ... | ... | @@ -3720,9 +3894,7 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv |
| 3720 | 3894 | // These are named declarations. They are analyzed only if marked `export`. |
| 3721 | 3895 | const inst_info = ip.getNav(nav).analysis.?.zir_index.resolveFull(ip) orelse continue; |
| 3722 | 3896 | const file = zcu.fileByIndex(inst_info.file); |
| 3723 | // If the file failed AstGen, the TrackedInst refers to the old ZIR. | |
| 3724 | const zir = if (file.status == .success_zir) file.zir else file.prev_zir.?.*; | |
| 3725 | const decl = zir.getDeclaration(inst_info.inst); | |
| 3897 | const decl = file.zir.?.getDeclaration(inst_info.inst); | |
| 3726 | 3898 | if (decl.linkage == .@"export") { |
| 3727 | 3899 | const unit: AnalUnit = .wrap(.{ .nav_val = nav }); |
| 3728 | 3900 | if (!result.contains(unit)) { |
| ... | ... | @@ -3858,7 +4030,7 @@ pub fn navSrcLine(zcu: *Zcu, nav_index: InternPool.Nav.Index) u32 { |
| 3858 | 4030 | const ip = &zcu.intern_pool; |
| 3859 | 4031 | const inst_info = ip.getNav(nav_index).srcInst(ip).resolveFull(ip).?; |
| 3860 | 4032 | const zir = zcu.fileByIndex(inst_info.file).zir; |
| 3861 | return zir.getDeclaration(inst_info.inst).src_line; | |
| 4033 | return zir.?.getDeclaration(inst_info.inst).src_line; | |
| 3862 | 4034 | } |
| 3863 | 4035 | |
| 3864 | 4036 | pub fn navValue(zcu: *const Zcu, nav_index: InternPool.Nav.Index) Value { |
| ... | ... | @@ -3910,10 +4082,6 @@ fn formatDependee(data: struct { dependee: InternPool.Dependee, zcu: *Zcu }, com |
| 3910 | 4082 | const zcu = data.zcu; |
| 3911 | 4083 | const ip = &zcu.intern_pool; |
| 3912 | 4084 | switch (data.dependee) { |
| 3913 | .file => |file| { | |
| 3914 | const file_path = zcu.fileByIndex(file).sub_file_path; | |
| 3915 | return writer.print("file('{s}')", .{file_path}); | |
| 3916 | }, | |
| 3917 | 4085 | .src_hash => |ti| { |
| 3918 | 4086 | const info = ti.resolveFull(ip) orelse { |
| 3919 | 4087 | return writer.writeAll("inst(<lost>)"); |
| ... | ... | @@ -3934,6 +4102,10 @@ fn formatDependee(data: struct { dependee: InternPool.Dependee, zcu: *Zcu }, com |
| 3934 | 4102 | .func => |f| return writer.print("ies('{}')", .{ip.getNav(f.owner_nav).fqn.fmt(ip)}), |
| 3935 | 4103 | else => unreachable, |
| 3936 | 4104 | }, |
| 4105 | .zon_file => |file| { | |
| 4106 | const file_path = zcu.fileByIndex(file).sub_file_path; | |
| 4107 | return writer.print("zon_file('{s}')", .{file_path}); | |
| 4108 | }, | |
| 3937 | 4109 | .embed_file => |ef_idx| { |
| 3938 | 4110 | const ef = ef_idx.get(zcu); |
| 3939 | 4111 | return writer.print("embed_file('{s}')", .{std.fs.path.fmtJoin(&.{ |
src/Zcu/PerThread.zig+263-288| ... | ... | @@ -26,6 +26,8 @@ const Type = @import("../Type.zig"); |
| 26 | 26 | const Value = @import("../Value.zig"); |
| 27 | 27 | const Zcu = @import("../Zcu.zig"); |
| 28 | 28 | const Zir = std.zig.Zir; |
| 29 | const Zoir = std.zig.Zoir; | |
| 30 | const ZonGen = std.zig.ZonGen; | |
| 29 | 31 | |
| 30 | 32 | zcu: *Zcu, |
| 31 | 33 | |
| ... | ... | @@ -73,7 +75,9 @@ pub fn destroyFile(pt: Zcu.PerThread, file_index: Zcu.File.Index) void { |
| 73 | 75 | if (!is_builtin) gpa.destroy(file); |
| 74 | 76 | } |
| 75 | 77 | |
| 76 | pub fn astGenFile( | |
| 78 | /// Ensures that `file` has up-to-date ZIR. If not, loads the ZIR cache or runs | |
| 79 | /// AstGen as needed. Also updates `file.status`. | |
| 80 | pub fn updateFile( | |
| 77 | 81 | pt: Zcu.PerThread, |
| 78 | 82 | file: *Zcu.File, |
| 79 | 83 | path_digest: Cache.BinDigest, |
| ... | ... | @@ -109,7 +113,7 @@ pub fn astGenFile( |
| 109 | 113 | |
| 110 | 114 | break :lock .shared; |
| 111 | 115 | }, |
| 112 | .parse_failure, .astgen_failure, .success_zir => lock: { | |
| 116 | .astgen_failure, .success => lock: { | |
| 113 | 117 | const unchanged_metadata = |
| 114 | 118 | stat.size == file.stat.size and |
| 115 | 119 | stat.mtime == file.stat.mtime and |
| ... | ... | @@ -126,6 +130,27 @@ pub fn astGenFile( |
| 126 | 130 | }, |
| 127 | 131 | }; |
| 128 | 132 | |
| 133 | // The old compile error, if any, is no longer relevant. | |
| 134 | pt.lockAndClearFileCompileError(file); | |
| 135 | ||
| 136 | // If `zir` is not null, and `prev_zir` is null, then `TrackedInst`s are associated with `zir`. | |
| 137 | // We need to keep it around! | |
| 138 | // As an optimization, also check `loweringFailed`; if true, but `prev_zir == null`, then this | |
| 139 | // file has never passed AstGen, so we actually need not cache the old ZIR. | |
| 140 | if (file.zir != null and file.prev_zir == null and !file.zir.?.loweringFailed()) { | |
| 141 | assert(file.prev_zir == null); | |
| 142 | const prev_zir_ptr = try gpa.create(Zir); | |
| 143 | file.prev_zir = prev_zir_ptr; | |
| 144 | prev_zir_ptr.* = file.zir.?; | |
| 145 | file.zir = null; | |
| 146 | } | |
| 147 | ||
| 148 | // If ZOIR is changing, then we need to invalidate dependencies on it | |
| 149 | if (file.zoir != null) file.zoir_invalidated = true; | |
| 150 | ||
| 151 | // We're going to re-load everything, so unload source, AST, ZIR, ZOIR. | |
| 152 | file.unload(gpa); | |
| 153 | ||
| 129 | 154 | // We ask for a lock in order to coordinate with other zig processes. |
| 130 | 155 | // If another process is already working on this file, we will get the cached |
| 131 | 156 | // version. Likewise if we're working on AstGen and another process asks for |
| ... | ... | @@ -180,190 +205,164 @@ pub fn astGenFile( |
| 180 | 205 | }; |
| 181 | 206 | defer cache_file.close(); |
| 182 | 207 | |
| 183 | while (true) { | |
| 184 | update: { | |
| 185 | // First we read the header to determine the lengths of arrays. | |
| 186 | const header = cache_file.reader().readStruct(Zir.Header) catch |err| switch (err) { | |
| 187 | // This can happen if Zig bails out of this function between creating | |
| 188 | // the cached file and writing it. | |
| 189 | error.EndOfStream => break :update, | |
| 190 | else => |e| return e, | |
| 191 | }; | |
| 192 | const unchanged_metadata = | |
| 193 | stat.size == header.stat_size and | |
| 194 | stat.mtime == header.stat_mtime and | |
| 195 | stat.inode == header.stat_inode; | |
| 196 | ||
| 197 | if (!unchanged_metadata) { | |
| 198 | log.debug("AstGen cache stale: {s}", .{file.sub_file_path}); | |
| 199 | break :update; | |
| 200 | } | |
| 201 | log.debug("AstGen cache hit: {s} instructions_len={d}", .{ | |
| 202 | file.sub_file_path, header.instructions_len, | |
| 203 | }); | |
| 204 | ||
| 205 | file.zir = Zcu.loadZirCacheBody(gpa, header, cache_file) catch |err| switch (err) { | |
| 206 | error.UnexpectedFileSize => { | |
| 207 | log.warn("unexpected EOF reading cached ZIR for {s}", .{file.sub_file_path}); | |
| 208 | break :update; | |
| 209 | }, | |
| 210 | else => |e| return e, | |
| 211 | }; | |
| 212 | file.zir_loaded = true; | |
| 213 | file.stat = .{ | |
| 214 | .size = header.stat_size, | |
| 215 | .inode = header.stat_inode, | |
| 216 | .mtime = header.stat_mtime, | |
| 217 | }; | |
| 218 | file.prev_status = file.status; | |
| 219 | file.status = .success_zir; | |
| 220 | log.debug("AstGen cached success: {s}", .{file.sub_file_path}); | |
| 221 | ||
| 222 | if (file.zir.hasCompileErrors()) { | |
| 223 | comp.mutex.lock(); | |
| 224 | defer comp.mutex.unlock(); | |
| 225 | try zcu.failed_files.putNoClobber(gpa, file, null); | |
| 226 | } | |
| 227 | if (file.zir.loweringFailed()) { | |
| 228 | file.status = .astgen_failure; | |
| 229 | return error.AnalysisFail; | |
| 230 | } | |
| 231 | return; | |
| 208 | const need_update = while (true) { | |
| 209 | const result = switch (file.getMode()) { | |
| 210 | inline else => |mode| try loadZirZoirCache(zcu, cache_file, stat, file, mode), | |
| 211 | }; | |
| 212 | switch (result) { | |
| 213 | .success => { | |
| 214 | log.debug("AstGen cached success: {s}", .{file.sub_file_path}); | |
| 215 | break false; | |
| 216 | }, | |
| 217 | .invalid => {}, | |
| 218 | .truncated => log.warn("unexpected EOF reading cached ZIR for {s}", .{file.sub_file_path}), | |
| 219 | .stale => log.debug("AstGen cache stale: {s}", .{file.sub_file_path}), | |
| 232 | 220 | } |
| 233 | 221 | |
| 234 | 222 | // If we already have the exclusive lock then it is our job to update. |
| 235 | if (builtin.os.tag == .wasi or lock == .exclusive) break; | |
| 223 | if (builtin.os.tag == .wasi or lock == .exclusive) break true; | |
| 236 | 224 | // Otherwise, unlock to give someone a chance to get the exclusive lock |
| 237 | 225 | // and then upgrade to an exclusive lock. |
| 238 | 226 | cache_file.unlock(); |
| 239 | 227 | lock = .exclusive; |
| 240 | 228 | try cache_file.lock(lock); |
| 241 | } | |
| 229 | }; | |
| 242 | 230 | |
| 243 | // The cache is definitely stale so delete the contents to avoid an underwrite later. | |
| 244 | cache_file.setEndPos(0) catch |err| switch (err) { | |
| 245 | error.FileTooBig => unreachable, // 0 is not too big | |
| 231 | if (need_update) { | |
| 232 | // The cache is definitely stale so delete the contents to avoid an underwrite later. | |
| 233 | cache_file.setEndPos(0) catch |err| switch (err) { | |
| 234 | error.FileTooBig => unreachable, // 0 is not too big | |
| 235 | else => |e| return e, | |
| 236 | }; | |
| 246 | 237 | |
| 247 | else => |e| return e, | |
| 248 | }; | |
| 238 | if (stat.size > std.math.maxInt(u32)) | |
| 239 | return error.FileTooBig; | |
| 249 | 240 | |
| 250 | pt.lockAndClearFileCompileError(file); | |
| 241 | const source = try gpa.allocSentinel(u8, @as(usize, @intCast(stat.size)), 0); | |
| 242 | defer if (file.source == null) gpa.free(source); | |
| 243 | const amt = try source_file.readAll(source); | |
| 244 | if (amt != stat.size) | |
| 245 | return error.UnexpectedEndOfFile; | |
| 251 | 246 | |
| 252 | // Previous ZIR is kept for two reasons: | |
| 253 | // | |
| 254 | // 1. In case an update to the file causes a Parse or AstGen failure, we | |
| 255 | // need to compare two successful ZIR files in order to proceed with an | |
| 256 | // incremental update. This avoids needlessly tossing out semantic | |
| 257 | // analysis work when an error is temporarily introduced. | |
| 258 | // | |
| 259 | // 2. In order to detect updates, we need to iterate over the intern pool | |
| 260 | // values while comparing old ZIR to new ZIR. This is better done in a | |
| 261 | // single-threaded context, so we need to keep both versions around | |
| 262 | // until that point in the pipeline. Previous ZIR data is freed after | |
| 263 | // that. | |
| 264 | if (file.zir_loaded and !file.zir.loweringFailed()) { | |
| 265 | assert(file.prev_zir == null); | |
| 266 | const prev_zir_ptr = try gpa.create(Zir); | |
| 267 | file.prev_zir = prev_zir_ptr; | |
| 268 | prev_zir_ptr.* = file.zir; | |
| 269 | file.zir = undefined; | |
| 270 | file.zir_loaded = false; | |
| 271 | } | |
| 272 | file.unload(gpa); | |
| 247 | file.source = source; | |
| 248 | ||
| 249 | // Any potential AST errors are converted to ZIR errors when we run AstGen/ZonGen. | |
| 250 | file.tree = try Ast.parse(gpa, source, file.getMode()); | |
| 273 | 251 | |
| 274 | if (stat.size > std.math.maxInt(u32)) | |
| 275 | return error.FileTooBig; | |
| 252 | switch (file.getMode()) { | |
| 253 | .zig => { | |
| 254 | file.zir = try AstGen.generate(gpa, file.tree.?); | |
| 255 | Zcu.saveZirCache(gpa, cache_file, stat, file.zir.?) catch |err| switch (err) { | |
| 256 | error.OutOfMemory => |e| return e, | |
| 257 | else => log.warn("unable to write cached ZIR code for {}{s} to {}{s}: {s}", .{ | |
| 258 | file.mod.root, file.sub_file_path, cache_directory, &hex_digest, @errorName(err), | |
| 259 | }), | |
| 260 | }; | |
| 261 | }, | |
| 262 | .zon => { | |
| 263 | file.zoir = try ZonGen.generate(gpa, file.tree.?, .{}); | |
| 264 | Zcu.saveZoirCache(cache_file, stat, file.zoir.?) catch |err| { | |
| 265 | log.warn("unable to write cached ZOIR code for {}{s} to {}{s}: {s}", .{ | |
| 266 | file.mod.root, file.sub_file_path, cache_directory, &hex_digest, @errorName(err), | |
| 267 | }); | |
| 268 | }; | |
| 269 | }, | |
| 270 | } | |
| 276 | 271 | |
| 277 | const source = try gpa.allocSentinel(u8, @as(usize, @intCast(stat.size)), 0); | |
| 278 | defer if (!file.source_loaded) gpa.free(source); | |
| 279 | const amt = try source_file.readAll(source); | |
| 280 | if (amt != stat.size) | |
| 281 | return error.UnexpectedEndOfFile; | |
| 272 | log.debug("AstGen fresh success: {s}", .{file.sub_file_path}); | |
| 273 | } | |
| 282 | 274 | |
| 283 | 275 | file.stat = .{ |
| 284 | 276 | .size = stat.size, |
| 285 | 277 | .inode = stat.inode, |
| 286 | 278 | .mtime = stat.mtime, |
| 287 | 279 | }; |
| 288 | file.source = source; | |
| 289 | file.source_loaded = true; | |
| 290 | 280 | |
| 291 | file.tree = try Ast.parse(gpa, source, .zig); | |
| 292 | file.tree_loaded = true; | |
| 281 | // Now, `zir` or `zoir` is definitely populated and up-to-date. | |
| 282 | // Mark file successes/failures as needed. | |
| 293 | 283 | |
| 294 | // Any potential AST errors are converted to ZIR errors here. | |
| 295 | file.zir = try AstGen.generate(gpa, file.tree); | |
| 296 | file.zir_loaded = true; | |
| 297 | file.prev_status = file.status; | |
| 298 | file.status = .success_zir; | |
| 299 | log.debug("AstGen fresh success: {s}", .{file.sub_file_path}); | |
| 284 | switch (file.getMode()) { | |
| 285 | .zig => { | |
| 286 | if (file.zir.?.hasCompileErrors()) { | |
| 287 | comp.mutex.lock(); | |
| 288 | defer comp.mutex.unlock(); | |
| 289 | try zcu.failed_files.putNoClobber(gpa, file, null); | |
| 290 | } | |
| 291 | if (file.zir.?.loweringFailed()) { | |
| 292 | file.status = .astgen_failure; | |
| 293 | } else { | |
| 294 | file.status = .success; | |
| 295 | } | |
| 296 | }, | |
| 297 | .zon => { | |
| 298 | if (file.zoir.?.hasCompileErrors()) { | |
| 299 | file.status = .astgen_failure; | |
| 300 | comp.mutex.lock(); | |
| 301 | defer comp.mutex.unlock(); | |
| 302 | try zcu.failed_files.putNoClobber(gpa, file, null); | |
| 303 | } else { | |
| 304 | file.status = .success; | |
| 305 | } | |
| 306 | }, | |
| 307 | } | |
| 300 | 308 | |
| 301 | const safety_buffer = if (Zcu.data_has_safety_tag) | |
| 302 | try gpa.alloc([8]u8, file.zir.instructions.len) | |
| 303 | else | |
| 304 | undefined; | |
| 305 | defer if (Zcu.data_has_safety_tag) gpa.free(safety_buffer); | |
| 306 | const data_ptr = if (Zcu.data_has_safety_tag) | |
| 307 | if (file.zir.instructions.len == 0) | |
| 308 | @as([*]const u8, undefined) | |
| 309 | else | |
| 310 | @as([*]const u8, @ptrCast(safety_buffer.ptr)) | |
| 311 | else | |
| 312 | @as([*]const u8, @ptrCast(file.zir.instructions.items(.data).ptr)); | |
| 313 | if (Zcu.data_has_safety_tag) { | |
| 314 | // The `Data` union has a safety tag but in the file format we store it without. | |
| 315 | for (file.zir.instructions.items(.data), 0..) |*data, i| { | |
| 316 | const as_struct: *const Zcu.HackDataLayout = @ptrCast(data); | |
| 317 | safety_buffer[i] = as_struct.data; | |
| 318 | } | |
| 309 | switch (file.status) { | |
| 310 | .never_loaded => unreachable, | |
| 311 | .retryable_failure => unreachable, | |
| 312 | .astgen_failure => return error.AnalysisFail, | |
| 313 | .success => return, | |
| 319 | 314 | } |
| 315 | } | |
| 320 | 316 | |
| 321 | const header: Zir.Header = .{ | |
| 322 | .instructions_len = @as(u32, @intCast(file.zir.instructions.len)), | |
| 323 | .string_bytes_len = @as(u32, @intCast(file.zir.string_bytes.len)), | |
| 324 | .extra_len = @as(u32, @intCast(file.zir.extra.len)), | |
| 317 | fn loadZirZoirCache( | |
| 318 | zcu: *Zcu, | |
| 319 | cache_file: std.fs.File, | |
| 320 | stat: std.fs.File.Stat, | |
| 321 | file: *Zcu.File, | |
| 322 | comptime mode: Ast.Mode, | |
| 323 | ) !enum { success, invalid, truncated, stale } { | |
| 324 | assert(file.getMode() == mode); | |
| 325 | 325 | |
| 326 | .stat_size = stat.size, | |
| 327 | .stat_inode = stat.inode, | |
| 328 | .stat_mtime = stat.mtime, | |
| 329 | }; | |
| 330 | var iovecs = [_]std.posix.iovec_const{ | |
| 331 | .{ | |
| 332 | .base = @as([*]const u8, @ptrCast(&header)), | |
| 333 | .len = @sizeOf(Zir.Header), | |
| 334 | }, | |
| 335 | .{ | |
| 336 | .base = @as([*]const u8, @ptrCast(file.zir.instructions.items(.tag).ptr)), | |
| 337 | .len = file.zir.instructions.len, | |
| 338 | }, | |
| 339 | .{ | |
| 340 | .base = data_ptr, | |
| 341 | .len = file.zir.instructions.len * 8, | |
| 342 | }, | |
| 343 | .{ | |
| 344 | .base = file.zir.string_bytes.ptr, | |
| 345 | .len = file.zir.string_bytes.len, | |
| 346 | }, | |
| 347 | .{ | |
| 348 | .base = @as([*]const u8, @ptrCast(file.zir.extra.ptr)), | |
| 349 | .len = file.zir.extra.len * 4, | |
| 350 | }, | |
| 326 | const gpa = zcu.gpa; | |
| 327 | ||
| 328 | const Header = switch (mode) { | |
| 329 | .zig => Zir.Header, | |
| 330 | .zon => Zoir.Header, | |
| 351 | 331 | }; |
| 352 | cache_file.writevAll(&iovecs) catch |err| { | |
| 353 | log.warn("unable to write cached ZIR code for {}{s} to {}{s}: {s}", .{ | |
| 354 | file.mod.root, file.sub_file_path, cache_directory, &hex_digest, @errorName(err), | |
| 355 | }); | |
| 332 | ||
| 333 | // First we read the header to determine the lengths of arrays. | |
| 334 | const header = cache_file.reader().readStruct(Header) catch |err| switch (err) { | |
| 335 | // This can happen if Zig bails out of this function between creating | |
| 336 | // the cached file and writing it. | |
| 337 | error.EndOfStream => return .invalid, | |
| 338 | else => |e| return e, | |
| 356 | 339 | }; |
| 357 | 340 | |
| 358 | if (file.zir.hasCompileErrors()) { | |
| 359 | comp.mutex.lock(); | |
| 360 | defer comp.mutex.unlock(); | |
| 361 | try zcu.failed_files.putNoClobber(gpa, file, null); | |
| 341 | const unchanged_metadata = | |
| 342 | stat.size == header.stat_size and | |
| 343 | stat.mtime == header.stat_mtime and | |
| 344 | stat.inode == header.stat_inode; | |
| 345 | ||
| 346 | if (!unchanged_metadata) { | |
| 347 | return .stale; | |
| 362 | 348 | } |
| 363 | if (file.zir.loweringFailed()) { | |
| 364 | file.status = .astgen_failure; | |
| 365 | return error.AnalysisFail; | |
| 349 | ||
| 350 | switch (mode) { | |
| 351 | .zig => { | |
| 352 | file.zir = Zcu.loadZirCacheBody(gpa, header, cache_file) catch |err| switch (err) { | |
| 353 | error.UnexpectedFileSize => return .truncated, | |
| 354 | else => |e| return e, | |
| 355 | }; | |
| 356 | }, | |
| 357 | .zon => { | |
| 358 | file.zoir = Zcu.loadZoirCacheBody(gpa, header, cache_file) catch |err| switch (err) { | |
| 359 | error.UnexpectedFileSize => return .truncated, | |
| 360 | else => |e| return e, | |
| 361 | }; | |
| 362 | }, | |
| 366 | 363 | } |
| 364 | ||
| 365 | return .success; | |
| 367 | 366 | } |
| 368 | 367 | |
| 369 | 368 | const UpdatedFile = struct { |
| ... | ... | @@ -384,24 +383,32 @@ pub fn updateZirRefs(pt: Zcu.PerThread) Allocator.Error!void { |
| 384 | 383 | const gpa = zcu.gpa; |
| 385 | 384 | |
| 386 | 385 | // We need to visit every updated File for every TrackedInst in InternPool. |
| 386 | // This only includes Zig files; ZON files are omitted. | |
| 387 | 387 | var updated_files: std.AutoArrayHashMapUnmanaged(Zcu.File.Index, UpdatedFile) = .empty; |
| 388 | 388 | defer cleanupUpdatedFiles(gpa, &updated_files); |
| 389 | ||
| 389 | 390 | for (zcu.import_table.values()) |file_index| { |
| 390 | 391 | const file = zcu.fileByIndex(file_index); |
| 391 | if (file.prev_status != file.status and file.prev_status != .never_loaded) { | |
| 392 | try zcu.markDependeeOutdated(.not_marked_po, .{ .file = file_index }); | |
| 392 | assert(file.status == .success); | |
| 393 | switch (file.getMode()) { | |
| 394 | .zig => {}, // logic below | |
| 395 | .zon => { | |
| 396 | if (file.zoir_invalidated) { | |
| 397 | try zcu.markDependeeOutdated(.not_marked_po, .{ .zon_file = file_index }); | |
| 398 | file.zoir_invalidated = false; | |
| 399 | } | |
| 400 | continue; | |
| 401 | }, | |
| 393 | 402 | } |
| 394 | 403 | const old_zir = file.prev_zir orelse continue; |
| 395 | const new_zir = file.zir; | |
| 404 | const new_zir = file.zir.?; | |
| 396 | 405 | const gop = try updated_files.getOrPut(gpa, file_index); |
| 397 | 406 | assert(!gop.found_existing); |
| 398 | 407 | gop.value_ptr.* = .{ |
| 399 | 408 | .file = file, |
| 400 | 409 | .inst_map = .{}, |
| 401 | 410 | }; |
| 402 | if (!new_zir.loweringFailed()) { | |
| 403 | try Zcu.mapOldZirToNew(gpa, old_zir.*, file.zir, &gop.value_ptr.inst_map); | |
| 404 | } | |
| 411 | try Zcu.mapOldZirToNew(gpa, old_zir.*, new_zir, &gop.value_ptr.inst_map); | |
| 405 | 412 | } |
| 406 | 413 | |
| 407 | 414 | if (updated_files.count() == 0) |
| ... | ... | @@ -421,13 +428,9 @@ pub fn updateZirRefs(pt: Zcu.PerThread) Allocator.Error!void { |
| 421 | 428 | .index = @intCast(tracked_inst_unwrapped_index), |
| 422 | 429 | }).wrap(ip); |
| 423 | 430 | const new_inst = updated_file.inst_map.get(old_inst) orelse { |
| 424 | // Tracking failed for this instruction. | |
| 425 | // This may be due to changes in the ZIR, or AstGen might have failed due to a very broken file. | |
| 426 | // Either way, invalidate associated `src_hash` deps. | |
| 427 | log.debug("tracking failed for %{d}{s}", .{ | |
| 428 | old_inst, | |
| 429 | if (file.zir.loweringFailed()) " due to AstGen failure" else "", | |
| 430 | }); | |
| 431 | // Tracking failed for this instruction due to changes in the ZIR. | |
| 432 | // Invalidate associated `src_hash` deps. | |
| 433 | log.debug("tracking failed for %{d}", .{old_inst}); | |
| 431 | 434 | tracked_inst.inst = .lost; |
| 432 | 435 | try zcu.markDependeeOutdated(.not_marked_po, .{ .src_hash = tracked_inst_index }); |
| 433 | 436 | continue; |
| ... | ... | @@ -435,7 +438,7 @@ pub fn updateZirRefs(pt: Zcu.PerThread) Allocator.Error!void { |
| 435 | 438 | tracked_inst.inst = InternPool.TrackedInst.MaybeLost.ZirIndex.wrap(new_inst); |
| 436 | 439 | |
| 437 | 440 | const old_zir = file.prev_zir.?.*; |
| 438 | const new_zir = file.zir; | |
| 441 | const new_zir = file.zir.?; | |
| 439 | 442 | const old_tag = old_zir.instructions.items(.tag)[@intFromEnum(old_inst)]; |
| 440 | 443 | const old_data = old_zir.instructions.items(.data)[@intFromEnum(old_inst)]; |
| 441 | 444 | |
| ... | ... | @@ -532,23 +535,19 @@ pub fn updateZirRefs(pt: Zcu.PerThread) Allocator.Error!void { |
| 532 | 535 | |
| 533 | 536 | for (updated_files.keys(), updated_files.values()) |file_index, updated_file| { |
| 534 | 537 | const file = updated_file.file; |
| 535 | if (file.zir.loweringFailed()) { | |
| 536 | // Keep `prev_zir` around: it's the last usable ZIR. | |
| 537 | // Don't update the namespace, as we have no new data to update *to*. | |
| 538 | } else { | |
| 539 | const prev_zir = file.prev_zir.?; | |
| 540 | file.prev_zir = null; | |
| 541 | prev_zir.deinit(gpa); | |
| 542 | gpa.destroy(prev_zir); | |
| 543 | ||
| 544 | // For every file which has changed, re-scan the namespace of the file's root struct type. | |
| 545 | // These types are special-cased because they don't have an enclosing declaration which will | |
| 546 | // be re-analyzed (causing the struct's namespace to be re-scanned). It's fine to do this | |
| 547 | // now because this work is fast (no actual Sema work is happening, we're just updating the | |
| 548 | // namespace contents). We must do this after updating ZIR refs above, since `scanNamespace` | |
| 549 | // will track some instructions. | |
| 550 | try pt.updateFileNamespace(file_index); | |
| 551 | } | |
| 538 | ||
| 539 | const prev_zir = file.prev_zir.?; | |
| 540 | file.prev_zir = null; | |
| 541 | prev_zir.deinit(gpa); | |
| 542 | gpa.destroy(prev_zir); | |
| 543 | ||
| 544 | // For every file which has changed, re-scan the namespace of the file's root struct type. | |
| 545 | // These types are special-cased because they don't have an enclosing declaration which will | |
| 546 | // be re-analyzed (causing the struct's namespace to be re-scanned). It's fine to do this | |
| 547 | // now because this work is fast (no actual Sema work is happening, we're just updating the | |
| 548 | // namespace contents). We must do this after updating ZIR refs above, since `scanNamespace` | |
| 549 | // will track some instructions. | |
| 550 | try pt.updateFileNamespace(file_index); | |
| 552 | 551 | } |
| 553 | 552 | } |
| 554 | 553 | |
| ... | ... | @@ -750,6 +749,7 @@ pub fn ensureComptimeUnitUpToDate(pt: Zcu.PerThread, cu_id: InternPool.ComptimeU |
| 750 | 749 | kv.value.destroy(gpa); |
| 751 | 750 | } |
| 752 | 751 | _ = zcu.transitive_failed_analysis.swapRemove(anal_unit); |
| 752 | zcu.intern_pool.removeDependenciesForDepender(gpa, anal_unit); | |
| 753 | 753 | } |
| 754 | 754 | } else { |
| 755 | 755 | // We can trust the current information about this unit. |
| ... | ... | @@ -801,14 +801,7 @@ fn analyzeComptimeUnit(pt: Zcu.PerThread, cu_id: InternPool.ComptimeUnit.Id) Zcu |
| 801 | 801 | |
| 802 | 802 | const inst_resolved = comptime_unit.zir_index.resolveFull(ip) orelse return error.AnalysisFail; |
| 803 | 803 | const file = zcu.fileByIndex(inst_resolved.file); |
| 804 | // TODO: stop the compiler ever reaching Sema if there are failed files. That way, this check is | |
| 805 | // unnecessary, and we can move the below `removeDependenciesForDepender` call up with its friends | |
| 806 | // in `ensureComptimeUnitUpToDate`. | |
| 807 | if (file.status != .success_zir) return error.AnalysisFail; | |
| 808 | const zir = file.zir; | |
| 809 | ||
| 810 | // We are about to re-analyze this unit; drop its depenndencies. | |
| 811 | zcu.intern_pool.removeDependenciesForDepender(gpa, anal_unit); | |
| 804 | const zir = file.zir.?; | |
| 812 | 805 | |
| 813 | 806 | try zcu.analysis_in_progress.put(gpa, anal_unit, {}); |
| 814 | 807 | defer assert(zcu.analysis_in_progress.swapRemove(anal_unit)); |
| ... | ... | @@ -928,6 +921,7 @@ pub fn ensureNavValUpToDate(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu |
| 928 | 921 | kv.value.destroy(gpa); |
| 929 | 922 | } |
| 930 | 923 | _ = zcu.transitive_failed_analysis.swapRemove(anal_unit); |
| 924 | ip.removeDependenciesForDepender(gpa, anal_unit); | |
| 931 | 925 | } else { |
| 932 | 926 | // We can trust the current information about this unit. |
| 933 | 927 | if (prev_failed) return error.AnalysisFail; |
| ... | ... | @@ -998,14 +992,7 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr |
| 998 | 992 | |
| 999 | 993 | const inst_resolved = old_nav.analysis.?.zir_index.resolveFull(ip) orelse return error.AnalysisFail; |
| 1000 | 994 | const file = zcu.fileByIndex(inst_resolved.file); |
| 1001 | // TODO: stop the compiler ever reaching Sema if there are failed files. That way, this check is | |
| 1002 | // unnecessary, and we can move the below `removeDependenciesForDepender` call up with its friends | |
| 1003 | // in `ensureComptimeUnitUpToDate`. | |
| 1004 | if (file.status != .success_zir) return error.AnalysisFail; | |
| 1005 | const zir = file.zir; | |
| 1006 | ||
| 1007 | // We are about to re-analyze this unit; drop its depenndencies. | |
| 1008 | zcu.intern_pool.removeDependenciesForDepender(gpa, anal_unit); | |
| 995 | const zir = file.zir.?; | |
| 1009 | 996 | |
| 1010 | 997 | try zcu.analysis_in_progress.put(gpa, anal_unit, {}); |
| 1011 | 998 | errdefer _ = zcu.analysis_in_progress.swapRemove(anal_unit); |
| ... | ... | @@ -1306,6 +1293,7 @@ pub fn ensureNavTypeUpToDate(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zc |
| 1306 | 1293 | kv.value.destroy(gpa); |
| 1307 | 1294 | } |
| 1308 | 1295 | _ = zcu.transitive_failed_analysis.swapRemove(anal_unit); |
| 1296 | ip.removeDependenciesForDepender(gpa, anal_unit); | |
| 1309 | 1297 | } else { |
| 1310 | 1298 | // We can trust the current information about this unit. |
| 1311 | 1299 | if (prev_failed) return error.AnalysisFail; |
| ... | ... | @@ -1376,14 +1364,7 @@ fn analyzeNavType(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileEr |
| 1376 | 1364 | |
| 1377 | 1365 | const inst_resolved = old_nav.analysis.?.zir_index.resolveFull(ip) orelse return error.AnalysisFail; |
| 1378 | 1366 | const file = zcu.fileByIndex(inst_resolved.file); |
| 1379 | // TODO: stop the compiler ever reaching Sema if there are failed files. That way, this check is | |
| 1380 | // unnecessary, and we can move the below `removeDependenciesForDepender` call up with its friends | |
| 1381 | // in `ensureComptimeUnitUpToDate`. | |
| 1382 | if (file.status != .success_zir) return error.AnalysisFail; | |
| 1383 | const zir = file.zir; | |
| 1384 | ||
| 1385 | // We are about to re-analyze this unit; drop its depenndencies. | |
| 1386 | zcu.intern_pool.removeDependenciesForDepender(gpa, anal_unit); | |
| 1367 | const zir = file.zir.?; | |
| 1387 | 1368 | |
| 1388 | 1369 | try zcu.analysis_in_progress.put(gpa, anal_unit, {}); |
| 1389 | 1370 | defer _ = zcu.analysis_in_progress.swapRemove(anal_unit); |
| ... | ... | @@ -1758,7 +1739,7 @@ fn createFileRootStruct( |
| 1758 | 1739 | const gpa = zcu.gpa; |
| 1759 | 1740 | const ip = &zcu.intern_pool; |
| 1760 | 1741 | const file = zcu.fileByIndex(file_index); |
| 1761 | const extended = file.zir.instructions.items(.data)[@intFromEnum(Zir.Inst.Index.main_struct_inst)].extended; | |
| 1742 | const extended = file.zir.?.instructions.items(.data)[@intFromEnum(Zir.Inst.Index.main_struct_inst)].extended; | |
| 1762 | 1743 | assert(extended.opcode == .struct_decl); |
| 1763 | 1744 | const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small); |
| 1764 | 1745 | assert(!small.has_captures_len); |
| ... | ... | @@ -1766,16 +1747,16 @@ fn createFileRootStruct( |
| 1766 | 1747 | assert(small.layout == .auto); |
| 1767 | 1748 | var extra_index: usize = extended.operand + @typeInfo(Zir.Inst.StructDecl).@"struct".fields.len; |
| 1768 | 1749 | const fields_len = if (small.has_fields_len) blk: { |
| 1769 | const fields_len = file.zir.extra[extra_index]; | |
| 1750 | const fields_len = file.zir.?.extra[extra_index]; | |
| 1770 | 1751 | extra_index += 1; |
| 1771 | 1752 | break :blk fields_len; |
| 1772 | 1753 | } else 0; |
| 1773 | 1754 | const decls_len = if (small.has_decls_len) blk: { |
| 1774 | const decls_len = file.zir.extra[extra_index]; | |
| 1755 | const decls_len = file.zir.?.extra[extra_index]; | |
| 1775 | 1756 | extra_index += 1; |
| 1776 | 1757 | break :blk decls_len; |
| 1777 | 1758 | } else 0; |
| 1778 | const decls = file.zir.bodySlice(extra_index, decls_len); | |
| 1759 | const decls = file.zir.?.bodySlice(extra_index, decls_len); | |
| 1779 | 1760 | extra_index += decls_len; |
| 1780 | 1761 | |
| 1781 | 1762 | const tracked_inst = try ip.trackZir(gpa, pt.tid, .{ |
| ... | ... | @@ -1833,7 +1814,6 @@ fn updateFileNamespace(pt: Zcu.PerThread, file_index: Zcu.File.Index) Allocator. |
| 1833 | 1814 | const zcu = pt.zcu; |
| 1834 | 1815 | |
| 1835 | 1816 | const file = zcu.fileByIndex(file_index); |
| 1836 | assert(file.status == .success_zir); | |
| 1837 | 1817 | const file_root_type = zcu.fileRootType(file_index); |
| 1838 | 1818 | if (file_root_type == .none) return; |
| 1839 | 1819 | |
| ... | ... | @@ -1844,17 +1824,17 @@ fn updateFileNamespace(pt: Zcu.PerThread, file_index: Zcu.File.Index) Allocator. |
| 1844 | 1824 | |
| 1845 | 1825 | const namespace_index = Type.fromInterned(file_root_type).getNamespaceIndex(zcu); |
| 1846 | 1826 | const decls = decls: { |
| 1847 | const extended = file.zir.instructions.items(.data)[@intFromEnum(Zir.Inst.Index.main_struct_inst)].extended; | |
| 1827 | const extended = file.zir.?.instructions.items(.data)[@intFromEnum(Zir.Inst.Index.main_struct_inst)].extended; | |
| 1848 | 1828 | const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small); |
| 1849 | 1829 | |
| 1850 | 1830 | var extra_index: usize = extended.operand + @typeInfo(Zir.Inst.StructDecl).@"struct".fields.len; |
| 1851 | 1831 | extra_index += @intFromBool(small.has_fields_len); |
| 1852 | 1832 | const decls_len = if (small.has_decls_len) blk: { |
| 1853 | const decls_len = file.zir.extra[extra_index]; | |
| 1833 | const decls_len = file.zir.?.extra[extra_index]; | |
| 1854 | 1834 | extra_index += 1; |
| 1855 | 1835 | break :blk decls_len; |
| 1856 | 1836 | } else 0; |
| 1857 | break :decls file.zir.bodySlice(extra_index, decls_len); | |
| 1837 | break :decls file.zir.?.bodySlice(extra_index, decls_len); | |
| 1858 | 1838 | }; |
| 1859 | 1839 | try pt.scanNamespace(namespace_index, decls); |
| 1860 | 1840 | zcu.namespacePtr(namespace_index).generation = zcu.generation; |
| ... | ... | @@ -1865,15 +1845,11 @@ fn semaFile(pt: Zcu.PerThread, file_index: Zcu.File.Index) Zcu.SemaError!void { |
| 1865 | 1845 | defer tracy.end(); |
| 1866 | 1846 | |
| 1867 | 1847 | const zcu = pt.zcu; |
| 1868 | const gpa = zcu.gpa; | |
| 1869 | 1848 | const file = zcu.fileByIndex(file_index); |
| 1870 | 1849 | assert(file.getMode() == .zig); |
| 1871 | 1850 | assert(zcu.fileRootType(file_index) == .none); |
| 1872 | 1851 | |
| 1873 | if (file.status != .success_zir) { | |
| 1874 | return error.AnalysisFail; | |
| 1875 | } | |
| 1876 | assert(file.zir_loaded); | |
| 1852 | assert(file.zir != null); | |
| 1877 | 1853 | |
| 1878 | 1854 | const new_namespace_index = try pt.createNamespace(.{ |
| 1879 | 1855 | .parent = .none, |
| ... | ... | @@ -1883,39 +1859,9 @@ fn semaFile(pt: Zcu.PerThread, file_index: Zcu.File.Index) Zcu.SemaError!void { |
| 1883 | 1859 | }); |
| 1884 | 1860 | const struct_ty = try pt.createFileRootStruct(file_index, new_namespace_index, false); |
| 1885 | 1861 | errdefer zcu.intern_pool.remove(pt.tid, struct_ty); |
| 1886 | ||
| 1887 | switch (zcu.comp.cache_use) { | |
| 1888 | .whole => |whole| if (whole.cache_manifest) |man| { | |
| 1889 | const source = file.getSource(gpa) catch |err| { | |
| 1890 | try pt.reportRetryableFileError(file_index, "unable to load source: {s}", .{@errorName(err)}); | |
| 1891 | return error.AnalysisFail; | |
| 1892 | }; | |
| 1893 | ||
| 1894 | const resolved_path = std.fs.path.resolve(gpa, &.{ | |
| 1895 | file.mod.root.root_dir.path orelse ".", | |
| 1896 | file.mod.root.sub_path, | |
| 1897 | file.sub_file_path, | |
| 1898 | }) catch |err| { | |
| 1899 | try pt.reportRetryableFileError(file_index, "unable to resolve path: {s}", .{@errorName(err)}); | |
| 1900 | return error.AnalysisFail; | |
| 1901 | }; | |
| 1902 | errdefer gpa.free(resolved_path); | |
| 1903 | ||
| 1904 | whole.cache_manifest_mutex.lock(); | |
| 1905 | defer whole.cache_manifest_mutex.unlock(); | |
| 1906 | man.addFilePostContents(resolved_path, source.bytes, source.stat) catch |err| switch (err) { | |
| 1907 | error.OutOfMemory => |e| return e, | |
| 1908 | else => { | |
| 1909 | try pt.reportRetryableFileError(file_index, "unable to update cache: {s}", .{@errorName(err)}); | |
| 1910 | return error.AnalysisFail; | |
| 1911 | }, | |
| 1912 | }; | |
| 1913 | }, | |
| 1914 | .incremental => {}, | |
| 1915 | } | |
| 1916 | 1862 | } |
| 1917 | 1863 | |
| 1918 | pub fn importPkg(pt: Zcu.PerThread, mod: *Module) !Zcu.ImportFileResult { | |
| 1864 | pub fn importPkg(pt: Zcu.PerThread, mod: *Module) Allocator.Error!Zcu.ImportFileResult { | |
| 1919 | 1865 | const zcu = pt.zcu; |
| 1920 | 1866 | const gpa = zcu.gpa; |
| 1921 | 1867 | |
| ... | ... | @@ -1983,15 +1929,12 @@ pub fn importPkg(pt: Zcu.PerThread, mod: *Module) !Zcu.ImportFileResult { |
| 1983 | 1929 | gop.value_ptr.* = new_file_index; |
| 1984 | 1930 | new_file.* = .{ |
| 1985 | 1931 | .sub_file_path = sub_file_path, |
| 1986 | .source = undefined, | |
| 1987 | .source_loaded = false, | |
| 1988 | .tree_loaded = false, | |
| 1989 | .zir_loaded = false, | |
| 1990 | 1932 | .stat = undefined, |
| 1991 | .tree = undefined, | |
| 1992 | .zir = undefined, | |
| 1933 | .source = null, | |
| 1934 | .tree = null, | |
| 1935 | .zir = null, | |
| 1936 | .zoir = null, | |
| 1993 | 1937 | .status = .never_loaded, |
| 1994 | .prev_status = .never_loaded, | |
| 1995 | 1938 | .mod = mod, |
| 1996 | 1939 | }; |
| 1997 | 1940 | |
| ... | ... | @@ -2004,13 +1947,19 @@ pub fn importPkg(pt: Zcu.PerThread, mod: *Module) !Zcu.ImportFileResult { |
| 2004 | 1947 | }; |
| 2005 | 1948 | } |
| 2006 | 1949 | |
| 2007 | /// Called from a worker thread during AstGen. | |
| 1950 | /// Called from a worker thread during AstGen (with the Compilation mutex held). | |
| 2008 | 1951 | /// Also called from Sema during semantic analysis. |
| 1952 | /// Does not attempt to load the file from disk; just returns a corresponding `*Zcu.File`. | |
| 2009 | 1953 | pub fn importFile( |
| 2010 | 1954 | pt: Zcu.PerThread, |
| 2011 | 1955 | cur_file: *Zcu.File, |
| 2012 | 1956 | import_string: []const u8, |
| 2013 | ) !Zcu.ImportFileResult { | |
| 1957 | ) error{ | |
| 1958 | OutOfMemory, | |
| 1959 | ModuleNotFound, | |
| 1960 | ImportOutsideModulePath, | |
| 1961 | CurrentWorkingDirectoryUnlinked, | |
| 1962 | }!Zcu.ImportFileResult { | |
| 2014 | 1963 | const zcu = pt.zcu; |
| 2015 | 1964 | const mod = cur_file.mod; |
| 2016 | 1965 | |
| ... | ... | @@ -2068,7 +2017,10 @@ pub fn importFile( |
| 2068 | 2017 | defer gpa.free(resolved_root_path); |
| 2069 | 2018 | |
| 2070 | 2019 | const sub_file_path = p: { |
| 2071 | const relative = try std.fs.path.relative(gpa, resolved_root_path, resolved_path); | |
| 2020 | const relative = std.fs.path.relative(gpa, resolved_root_path, resolved_path) catch |err| switch (err) { | |
| 2021 | error.Unexpected => unreachable, | |
| 2022 | else => |e| return e, | |
| 2023 | }; | |
| 2072 | 2024 | errdefer gpa.free(relative); |
| 2073 | 2025 | |
| 2074 | 2026 | if (!isUpDir(relative) and !std.fs.path.isAbsolute(relative)) { |
| ... | ... | @@ -2096,15 +2048,15 @@ pub fn importFile( |
| 2096 | 2048 | gop.value_ptr.* = new_file_index; |
| 2097 | 2049 | new_file.* = .{ |
| 2098 | 2050 | .sub_file_path = sub_file_path, |
| 2099 | .source = undefined, | |
| 2100 | .source_loaded = false, | |
| 2101 | .tree_loaded = false, | |
| 2102 | .zir_loaded = false, | |
| 2103 | .stat = undefined, | |
| 2104 | .tree = undefined, | |
| 2105 | .zir = undefined, | |
| 2051 | ||
| 2106 | 2052 | .status = .never_loaded, |
| 2107 | .prev_status = .never_loaded, | |
| 2053 | .stat = undefined, | |
| 2054 | ||
| 2055 | .source = null, | |
| 2056 | .tree = null, | |
| 2057 | .zir = null, | |
| 2058 | .zoir = null, | |
| 2059 | ||
| 2108 | 2060 | .mod = mod, |
| 2109 | 2061 | }; |
| 2110 | 2062 | |
| ... | ... | @@ -2441,7 +2393,7 @@ const ScanDeclIter = struct { |
| 2441 | 2393 | const namespace = zcu.namespacePtr(namespace_index); |
| 2442 | 2394 | const gpa = zcu.gpa; |
| 2443 | 2395 | const file = namespace.fileScope(zcu); |
| 2444 | const zir = file.zir; | |
| 2396 | const zir = file.zir.?; | |
| 2445 | 2397 | const ip = &zcu.intern_pool; |
| 2446 | 2398 | |
| 2447 | 2399 | const decl = zir.getDeclaration(decl_inst); |
| ... | ... | @@ -2591,7 +2543,7 @@ fn analyzeFnBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaE |
| 2591 | 2543 | const func = zcu.funcInfo(func_index); |
| 2592 | 2544 | const inst_info = func.zir_body_inst.resolveFull(ip) orelse return error.AnalysisFail; |
| 2593 | 2545 | const file = zcu.fileByIndex(inst_info.file); |
| 2594 | const zir = file.zir; | |
| 2546 | const zir = file.zir.?; | |
| 2595 | 2547 | |
| 2596 | 2548 | try zcu.analysis_in_progress.put(gpa, anal_unit, {}); |
| 2597 | 2549 | errdefer _ = zcu.analysis_in_progress.swapRemove(anal_unit); |
| ... | ... | @@ -2843,11 +2795,32 @@ pub fn getErrorValueFromSlice(pt: Zcu.PerThread, name: []const u8) Allocator.Err |
| 2843 | 2795 | /// Removes any entry from `Zcu.failed_files` associated with `file`. Acquires `Compilation.mutex` as needed. |
| 2844 | 2796 | /// `file.zir` must be unchanged from the last update, as it is used to determine if there is such an entry. |
| 2845 | 2797 | fn lockAndClearFileCompileError(pt: Zcu.PerThread, file: *Zcu.File) void { |
| 2846 | if (!file.zir_loaded or !file.zir.hasCompileErrors()) return; | |
| 2798 | const maybe_has_error = switch (file.status) { | |
| 2799 | .never_loaded => false, | |
| 2800 | .retryable_failure => true, | |
| 2801 | .astgen_failure => true, | |
| 2802 | .success => switch (file.getMode()) { | |
| 2803 | .zig => has_error: { | |
| 2804 | const zir = file.zir orelse break :has_error false; | |
| 2805 | break :has_error zir.hasCompileErrors(); | |
| 2806 | }, | |
| 2807 | .zon => has_error: { | |
| 2808 | const zoir = file.zoir orelse break :has_error false; | |
| 2809 | break :has_error zoir.hasCompileErrors(); | |
| 2810 | }, | |
| 2811 | }, | |
| 2812 | }; | |
| 2813 | ||
| 2814 | // If runtime safety is on, let's quickly lock the mutex and check anyway. | |
| 2815 | if (!maybe_has_error and !std.debug.runtime_safety) { | |
| 2816 | return; | |
| 2817 | } | |
| 2818 | ||
| 2847 | 2819 | pt.zcu.comp.mutex.lock(); |
| 2848 | 2820 | defer pt.zcu.comp.mutex.unlock(); |
| 2849 | 2821 | if (pt.zcu.failed_files.fetchSwapRemove(file)) |kv| { |
| 2850 | if (kv.value) |msg| msg.destroy(pt.zcu.gpa); // Delete previous error message. | |
| 2822 | assert(maybe_has_error); // the runtime safety case above | |
| 2823 | if (kv.value) |msg| msg.destroy(pt.zcu.gpa); // delete previous error message | |
| 2851 | 2824 | } |
| 2852 | 2825 | } |
| 2853 | 2826 | |
| ... | ... | @@ -3203,6 +3176,7 @@ pub fn linkerUpdateLineNumber(pt: Zcu.PerThread, ti: InternPool.TrackedInst.Inde |
| 3203 | 3176 | } |
| 3204 | 3177 | } |
| 3205 | 3178 | |
| 3179 | /// Sets `File.status` of `file_index` to `retryable_failure`, and stores an error in `pt.zcu.failed_files`. | |
| 3206 | 3180 | pub fn reportRetryableAstGenError( |
| 3207 | 3181 | pt: Zcu.PerThread, |
| 3208 | 3182 | src: Zcu.AstGenSrc, |
| ... | ... | @@ -3238,13 +3212,18 @@ pub fn reportRetryableAstGenError( |
| 3238 | 3212 | }); |
| 3239 | 3213 | errdefer err_msg.destroy(gpa); |
| 3240 | 3214 | |
| 3241 | { | |
| 3242 | zcu.comp.mutex.lock(); | |
| 3243 | defer zcu.comp.mutex.unlock(); | |
| 3244 | try zcu.failed_files.putNoClobber(gpa, file, err_msg); | |
| 3215 | zcu.comp.mutex.lock(); | |
| 3216 | defer zcu.comp.mutex.unlock(); | |
| 3217 | const gop = try zcu.failed_files.getOrPut(gpa, file); | |
| 3218 | if (gop.found_existing) { | |
| 3219 | if (gop.value_ptr.*) |old_err_msg| { | |
| 3220 | old_err_msg.destroy(gpa); | |
| 3221 | } | |
| 3245 | 3222 | } |
| 3223 | gop.value_ptr.* = err_msg; | |
| 3246 | 3224 | } |
| 3247 | 3225 | |
| 3226 | /// Sets `File.status` of `file_index` to `retryable_failure`, and stores an error in `pt.zcu.failed_files`. | |
| 3248 | 3227 | pub fn reportRetryableFileError( |
| 3249 | 3228 | pt: Zcu.PerThread, |
| 3250 | 3229 | file_index: Zcu.File.Index, |
| ... | ... | @@ -3778,8 +3757,7 @@ fn recreateStructType( |
| 3778 | 3757 | |
| 3779 | 3758 | const inst_info = key.zir_index.resolveFull(ip).?; |
| 3780 | 3759 | const file = zcu.fileByIndex(inst_info.file); |
| 3781 | assert(file.status == .success_zir); // otherwise inst tracking failed | |
| 3782 | const zir = file.zir; | |
| 3760 | const zir = file.zir.?; | |
| 3783 | 3761 | |
| 3784 | 3762 | assert(zir.instructions.items(.tag)[@intFromEnum(inst_info.inst)] == .extended); |
| 3785 | 3763 | const extended = zir.instructions.items(.data)[@intFromEnum(inst_info.inst)].extended; |
| ... | ... | @@ -3851,8 +3829,7 @@ fn recreateUnionType( |
| 3851 | 3829 | |
| 3852 | 3830 | const inst_info = key.zir_index.resolveFull(ip).?; |
| 3853 | 3831 | const file = zcu.fileByIndex(inst_info.file); |
| 3854 | assert(file.status == .success_zir); // otherwise inst tracking failed | |
| 3855 | const zir = file.zir; | |
| 3832 | const zir = file.zir.?; | |
| 3856 | 3833 | |
| 3857 | 3834 | assert(zir.instructions.items(.tag)[@intFromEnum(inst_info.inst)] == .extended); |
| 3858 | 3835 | const extended = zir.instructions.items(.data)[@intFromEnum(inst_info.inst)].extended; |
| ... | ... | @@ -3938,8 +3915,7 @@ fn recreateEnumType( |
| 3938 | 3915 | |
| 3939 | 3916 | const inst_info = key.zir_index.resolveFull(ip).?; |
| 3940 | 3917 | const file = zcu.fileByIndex(inst_info.file); |
| 3941 | assert(file.status == .success_zir); // otherwise inst tracking failed | |
| 3942 | const zir = file.zir; | |
| 3918 | const zir = file.zir.?; | |
| 3943 | 3919 | |
| 3944 | 3920 | assert(zir.instructions.items(.tag)[@intFromEnum(inst_info.inst)] == .extended); |
| 3945 | 3921 | const extended = zir.instructions.items(.data)[@intFromEnum(inst_info.inst)].extended; |
| ... | ... | @@ -4082,8 +4058,7 @@ pub fn ensureNamespaceUpToDate(pt: Zcu.PerThread, namespace_index: Zcu.Namespace |
| 4082 | 4058 | |
| 4083 | 4059 | const inst_info = key.zir_index.resolveFull(ip) orelse return error.AnalysisFail; |
| 4084 | 4060 | const file = zcu.fileByIndex(inst_info.file); |
| 4085 | if (file.status != .success_zir) return error.AnalysisFail; | |
| 4086 | const zir = file.zir; | |
| 4061 | const zir = file.zir.?; | |
| 4087 | 4062 | |
| 4088 | 4063 | assert(zir.instructions.items(.tag)[@intFromEnum(inst_info.inst)] == .extended); |
| 4089 | 4064 | const extended = zir.instructions.items(.data)[@intFromEnum(inst_info.inst)].extended; |
src/link.zig+1-2| ... | ... | @@ -750,8 +750,7 @@ pub const File = struct { |
| 750 | 750 | { |
| 751 | 751 | const ti = ti_id.resolveFull(&pt.zcu.intern_pool).?; |
| 752 | 752 | const file = pt.zcu.fileByIndex(ti.file); |
| 753 | assert(file.zir_loaded); | |
| 754 | const inst = file.zir.instructions.get(@intFromEnum(ti.inst)); | |
| 753 | const inst = file.zir.?.instructions.get(@intFromEnum(ti.inst)); | |
| 755 | 754 | assert(inst.tag == .declaration); |
| 756 | 755 | } |
| 757 | 756 |
src/link/Dwarf.zig+7-10| ... | ... | @@ -2358,8 +2358,7 @@ fn initWipNavInner( |
| 2358 | 2358 | const nav = ip.getNav(nav_index); |
| 2359 | 2359 | const inst_info = nav.srcInst(ip).resolveFull(ip).?; |
| 2360 | 2360 | const file = zcu.fileByIndex(inst_info.file); |
| 2361 | assert(file.zir_loaded); | |
| 2362 | const decl = file.zir.getDeclaration(inst_info.inst); | |
| 2361 | const decl = file.zir.?.getDeclaration(inst_info.inst); | |
| 2363 | 2362 | log.debug("initWipNav({s}:{d}:{d} %{d} = {})", .{ |
| 2364 | 2363 | file.sub_file_path, |
| 2365 | 2364 | decl.src_line + 1, |
| ... | ... | @@ -2373,7 +2372,7 @@ fn initWipNavInner( |
| 2373 | 2372 | switch (nav_key) { |
| 2374 | 2373 | // Ignore @extern |
| 2375 | 2374 | .@"extern" => |@"extern"| if (decl.linkage != .@"extern" or |
| 2376 | !@"extern".name.eqlSlice(file.zir.nullTerminatedString(decl.name), ip)) return null, | |
| 2375 | !@"extern".name.eqlSlice(file.zir.?.nullTerminatedString(decl.name), ip)) return null, | |
| 2377 | 2376 | else => {}, |
| 2378 | 2377 | } |
| 2379 | 2378 | |
| ... | ... | @@ -2696,8 +2695,7 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo |
| 2696 | 2695 | const nav = ip.getNav(nav_index); |
| 2697 | 2696 | const inst_info = nav.srcInst(ip).resolveFull(ip).?; |
| 2698 | 2697 | const file = zcu.fileByIndex(inst_info.file); |
| 2699 | assert(file.zir_loaded); | |
| 2700 | const decl = file.zir.getDeclaration(inst_info.inst); | |
| 2698 | const decl = file.zir.?.getDeclaration(inst_info.inst); | |
| 2701 | 2699 | log.debug("updateComptimeNav({s}:{d}:{d} %{d} = {})", .{ |
| 2702 | 2700 | file.sub_file_path, |
| 2703 | 2701 | decl.src_line + 1, |
| ... | ... | @@ -4097,7 +4095,7 @@ pub fn updateContainerType(dwarf: *Dwarf, pt: Zcu.PerThread, type_index: InternP |
| 4097 | 4095 | // if a newly-tracked instruction can be a type's owner `zir_index`. |
| 4098 | 4096 | comptime assert(Zir.inst_tracking_version == 0); |
| 4099 | 4097 | |
| 4100 | const decl_inst = file.zir.instructions.get(@intFromEnum(inst_info.inst)); | |
| 4098 | const decl_inst = file.zir.?.instructions.get(@intFromEnum(inst_info.inst)); | |
| 4101 | 4099 | const name_strat: Zir.Inst.NameStrategy = switch (decl_inst.tag) { |
| 4102 | 4100 | .struct_init, .struct_init_ref, .struct_init_anon => .anon, |
| 4103 | 4101 | .extended => switch (decl_inst.data.extended.opcode) { |
| ... | ... | @@ -4301,14 +4299,13 @@ pub fn updateLineNumber(dwarf: *Dwarf, zcu: *Zcu, zir_index: InternPool.TrackedI |
| 4301 | 4299 | const inst_info = zir_index.resolveFull(ip).?; |
| 4302 | 4300 | assert(inst_info.inst != .main_struct_inst); |
| 4303 | 4301 | const file = zcu.fileByIndex(inst_info.file); |
| 4304 | assert(file.zir_loaded); | |
| 4305 | const decl = file.zir.getDeclaration(inst_info.inst); | |
| 4302 | const decl = file.zir.?.getDeclaration(inst_info.inst); | |
| 4306 | 4303 | log.debug("updateLineNumber({s}:{d}:{d} %{d} = {s})", .{ |
| 4307 | 4304 | file.sub_file_path, |
| 4308 | 4305 | decl.src_line + 1, |
| 4309 | 4306 | decl.src_column + 1, |
| 4310 | 4307 | @intFromEnum(inst_info.inst), |
| 4311 | file.zir.nullTerminatedString(decl.name), | |
| 4308 | file.zir.?.nullTerminatedString(decl.name), | |
| 4312 | 4309 | }); |
| 4313 | 4310 | |
| 4314 | 4311 | var line_buf: [4]u8 = undefined; |
| ... | ... | @@ -4661,7 +4658,7 @@ pub fn flushModule(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void { |
| 4661 | 4658 | .target_unit = StringSection.unit, |
| 4662 | 4659 | .target_entry = (try dwarf.debug_line_str.addString( |
| 4663 | 4660 | dwarf, |
| 4664 | if (file.mod.builtin_file == file) file.source else "", | |
| 4661 | if (file.mod.builtin_file == file) file.source.? else "", | |
| 4665 | 4662 | )).toOptional(), |
| 4666 | 4663 | }); |
| 4667 | 4664 | header.appendNTimesAssumeCapacity(0, dwarf.sectionOffsetBytes()); |
src/main.zig+49-66| ... | ... | @@ -3636,7 +3636,7 @@ fn buildOutputType( |
| 3636 | 3636 | |
| 3637 | 3637 | if (show_builtin) { |
| 3638 | 3638 | const builtin_mod = comp.root_mod.getBuiltinDependency(); |
| 3639 | const source = builtin_mod.builtin_file.?.source; | |
| 3639 | const source = builtin_mod.builtin_file.?.source.?; | |
| 3640 | 3640 | return std.io.getStdOut().writeAll(source); |
| 3641 | 3641 | } |
| 3642 | 3642 | switch (listen) { |
| ... | ... | @@ -6134,15 +6134,12 @@ fn cmdAstCheck( |
| 6134 | 6134 | |
| 6135 | 6135 | var file: Zcu.File = .{ |
| 6136 | 6136 | .status = .never_loaded, |
| 6137 | .prev_status = .never_loaded, | |
| 6138 | .source_loaded = false, | |
| 6139 | .tree_loaded = false, | |
| 6140 | .zir_loaded = false, | |
| 6141 | 6137 | .sub_file_path = undefined, |
| 6142 | .source = undefined, | |
| 6143 | 6138 | .stat = undefined, |
| 6144 | .tree = undefined, | |
| 6145 | .zir = undefined, | |
| 6139 | .source = null, | |
| 6140 | .tree = null, | |
| 6141 | .zir = null, | |
| 6142 | .zoir = null, | |
| 6146 | 6143 | .mod = undefined, |
| 6147 | 6144 | }; |
| 6148 | 6145 | if (zig_source_file) |file_name| { |
| ... | ... | @@ -6163,7 +6160,6 @@ fn cmdAstCheck( |
| 6163 | 6160 | |
| 6164 | 6161 | file.sub_file_path = file_name; |
| 6165 | 6162 | file.source = source; |
| 6166 | file.source_loaded = true; | |
| 6167 | 6163 | file.stat = .{ |
| 6168 | 6164 | .size = stat.size, |
| 6169 | 6165 | .inode = stat.inode, |
| ... | ... | @@ -6176,7 +6172,6 @@ fn cmdAstCheck( |
| 6176 | 6172 | }; |
| 6177 | 6173 | file.sub_file_path = "<stdin>"; |
| 6178 | 6174 | file.source = source; |
| 6179 | file.source_loaded = true; | |
| 6180 | 6175 | file.stat.size = source.len; |
| 6181 | 6176 | } |
| 6182 | 6177 | |
| ... | ... | @@ -6196,17 +6191,15 @@ fn cmdAstCheck( |
| 6196 | 6191 | .fully_qualified_name = "root", |
| 6197 | 6192 | }); |
| 6198 | 6193 | |
| 6199 | file.tree = try Ast.parse(gpa, file.source, mode); | |
| 6200 | file.tree_loaded = true; | |
| 6201 | defer file.tree.deinit(gpa); | |
| 6194 | file.tree = try Ast.parse(gpa, file.source.?, mode); | |
| 6195 | defer file.tree.?.deinit(gpa); | |
| 6202 | 6196 | |
| 6203 | 6197 | switch (mode) { |
| 6204 | 6198 | .zig => { |
| 6205 | file.zir = try AstGen.generate(gpa, file.tree); | |
| 6206 | file.zir_loaded = true; | |
| 6207 | defer file.zir.deinit(gpa); | |
| 6199 | file.zir = try AstGen.generate(gpa, file.tree.?); | |
| 6200 | defer file.zir.?.deinit(gpa); | |
| 6208 | 6201 | |
| 6209 | if (file.zir.hasCompileErrors()) { | |
| 6202 | if (file.zir.?.hasCompileErrors()) { | |
| 6210 | 6203 | var wip_errors: std.zig.ErrorBundle.Wip = undefined; |
| 6211 | 6204 | try wip_errors.init(gpa); |
| 6212 | 6205 | defer wip_errors.deinit(); |
| ... | ... | @@ -6215,13 +6208,13 @@ fn cmdAstCheck( |
| 6215 | 6208 | defer error_bundle.deinit(gpa); |
| 6216 | 6209 | error_bundle.renderToStdErr(color.renderOptions()); |
| 6217 | 6210 | |
| 6218 | if (file.zir.loweringFailed()) { | |
| 6211 | if (file.zir.?.loweringFailed()) { | |
| 6219 | 6212 | process.exit(1); |
| 6220 | 6213 | } |
| 6221 | 6214 | } |
| 6222 | 6215 | |
| 6223 | 6216 | if (!want_output_text) { |
| 6224 | if (file.zir.hasCompileErrors()) { | |
| 6217 | if (file.zir.?.hasCompileErrors()) { | |
| 6225 | 6218 | process.exit(1); |
| 6226 | 6219 | } else { |
| 6227 | 6220 | return cleanExit(); |
| ... | ... | @@ -6233,18 +6226,18 @@ fn cmdAstCheck( |
| 6233 | 6226 | |
| 6234 | 6227 | { |
| 6235 | 6228 | const token_bytes = @sizeOf(Ast.TokenList) + |
| 6236 | file.tree.tokens.len * (@sizeOf(std.zig.Token.Tag) + @sizeOf(Ast.ByteOffset)); | |
| 6237 | const tree_bytes = @sizeOf(Ast) + file.tree.nodes.len * | |
| 6229 | file.tree.?.tokens.len * (@sizeOf(std.zig.Token.Tag) + @sizeOf(Ast.ByteOffset)); | |
| 6230 | const tree_bytes = @sizeOf(Ast) + file.tree.?.nodes.len * | |
| 6238 | 6231 | (@sizeOf(Ast.Node.Tag) + |
| 6239 | 6232 | @sizeOf(Ast.Node.Data) + |
| 6240 | 6233 | @sizeOf(Ast.TokenIndex)); |
| 6241 | const instruction_bytes = file.zir.instructions.len * | |
| 6234 | const instruction_bytes = file.zir.?.instructions.len * | |
| 6242 | 6235 | // Here we don't use @sizeOf(Zir.Inst.Data) because it would include |
| 6243 | 6236 | // the debug safety tag but we want to measure release size. |
| 6244 | 6237 | (@sizeOf(Zir.Inst.Tag) + 8); |
| 6245 | const extra_bytes = file.zir.extra.len * @sizeOf(u32); | |
| 6238 | const extra_bytes = file.zir.?.extra.len * @sizeOf(u32); | |
| 6246 | 6239 | const total_bytes = @sizeOf(Zir) + instruction_bytes + extra_bytes + |
| 6247 | file.zir.string_bytes.len * @sizeOf(u8); | |
| 6240 | file.zir.?.string_bytes.len * @sizeOf(u8); | |
| 6248 | 6241 | const stdout = io.getStdOut(); |
| 6249 | 6242 | const fmtIntSizeBin = std.fmt.fmtIntSizeBin; |
| 6250 | 6243 | // zig fmt: off |
| ... | ... | @@ -6258,27 +6251,27 @@ fn cmdAstCheck( |
| 6258 | 6251 | \\# Extra Data Items: {d} ({}) |
| 6259 | 6252 | \\ |
| 6260 | 6253 | , .{ |
| 6261 | fmtIntSizeBin(file.source.len), | |
| 6262 | file.tree.tokens.len, fmtIntSizeBin(token_bytes), | |
| 6263 | file.tree.nodes.len, fmtIntSizeBin(tree_bytes), | |
| 6254 | fmtIntSizeBin(file.source.?.len), | |
| 6255 | file.tree.?.tokens.len, fmtIntSizeBin(token_bytes), | |
| 6256 | file.tree.?.nodes.len, fmtIntSizeBin(tree_bytes), | |
| 6264 | 6257 | fmtIntSizeBin(total_bytes), |
| 6265 | file.zir.instructions.len, fmtIntSizeBin(instruction_bytes), | |
| 6266 | fmtIntSizeBin(file.zir.string_bytes.len), | |
| 6267 | file.zir.extra.len, fmtIntSizeBin(extra_bytes), | |
| 6258 | file.zir.?.instructions.len, fmtIntSizeBin(instruction_bytes), | |
| 6259 | fmtIntSizeBin(file.zir.?.string_bytes.len), | |
| 6260 | file.zir.?.extra.len, fmtIntSizeBin(extra_bytes), | |
| 6268 | 6261 | }); |
| 6269 | 6262 | // zig fmt: on |
| 6270 | 6263 | } |
| 6271 | 6264 | |
| 6272 | 6265 | try @import("print_zir.zig").renderAsTextToFile(gpa, &file, io.getStdOut()); |
| 6273 | 6266 | |
| 6274 | if (file.zir.hasCompileErrors()) { | |
| 6267 | if (file.zir.?.hasCompileErrors()) { | |
| 6275 | 6268 | process.exit(1); |
| 6276 | 6269 | } else { |
| 6277 | 6270 | return cleanExit(); |
| 6278 | 6271 | } |
| 6279 | 6272 | }, |
| 6280 | 6273 | .zon => { |
| 6281 | const zoir = try ZonGen.generate(gpa, file.tree, .{}); | |
| 6274 | const zoir = try ZonGen.generate(gpa, file.tree.?, .{}); | |
| 6282 | 6275 | defer zoir.deinit(gpa); |
| 6283 | 6276 | |
| 6284 | 6277 | if (zoir.hasCompileErrors()) { |
| ... | ... | @@ -6289,7 +6282,7 @@ fn cmdAstCheck( |
| 6289 | 6282 | { |
| 6290 | 6283 | const src_path = try file.fullPath(gpa); |
| 6291 | 6284 | defer gpa.free(src_path); |
| 6292 | try wip_errors.addZoirErrorMessages(zoir, file.tree, file.source, src_path); | |
| 6285 | try wip_errors.addZoirErrorMessages(zoir, file.tree.?, file.source.?, src_path); | |
| 6293 | 6286 | } |
| 6294 | 6287 | |
| 6295 | 6288 | var error_bundle = try wip_errors.toOwnedBundle(""); |
| ... | ... | @@ -6518,27 +6511,24 @@ fn cmdDumpZir( |
| 6518 | 6511 | |
| 6519 | 6512 | var file: Zcu.File = .{ |
| 6520 | 6513 | .status = .never_loaded, |
| 6521 | .prev_status = .never_loaded, | |
| 6522 | .source_loaded = false, | |
| 6523 | .tree_loaded = false, | |
| 6524 | .zir_loaded = true, | |
| 6525 | 6514 | .sub_file_path = undefined, |
| 6526 | .source = undefined, | |
| 6527 | 6515 | .stat = undefined, |
| 6528 | .tree = undefined, | |
| 6516 | .source = null, | |
| 6517 | .tree = null, | |
| 6529 | 6518 | .zir = try Zcu.loadZirCache(gpa, f), |
| 6519 | .zoir = null, | |
| 6530 | 6520 | .mod = undefined, |
| 6531 | 6521 | }; |
| 6532 | defer file.zir.deinit(gpa); | |
| 6522 | defer file.zir.?.deinit(gpa); | |
| 6533 | 6523 | |
| 6534 | 6524 | { |
| 6535 | const instruction_bytes = file.zir.instructions.len * | |
| 6525 | const instruction_bytes = file.zir.?.instructions.len * | |
| 6536 | 6526 | // Here we don't use @sizeOf(Zir.Inst.Data) because it would include |
| 6537 | 6527 | // the debug safety tag but we want to measure release size. |
| 6538 | 6528 | (@sizeOf(Zir.Inst.Tag) + 8); |
| 6539 | const extra_bytes = file.zir.extra.len * @sizeOf(u32); | |
| 6529 | const extra_bytes = file.zir.?.extra.len * @sizeOf(u32); | |
| 6540 | 6530 | const total_bytes = @sizeOf(Zir) + instruction_bytes + extra_bytes + |
| 6541 | file.zir.string_bytes.len * @sizeOf(u8); | |
| 6531 | file.zir.?.string_bytes.len * @sizeOf(u8); | |
| 6542 | 6532 | const stdout = io.getStdOut(); |
| 6543 | 6533 | const fmtIntSizeBin = std.fmt.fmtIntSizeBin; |
| 6544 | 6534 | // zig fmt: off |
| ... | ... | @@ -6550,9 +6540,9 @@ fn cmdDumpZir( |
| 6550 | 6540 | \\ |
| 6551 | 6541 | , .{ |
| 6552 | 6542 | fmtIntSizeBin(total_bytes), |
| 6553 | file.zir.instructions.len, fmtIntSizeBin(instruction_bytes), | |
| 6554 | fmtIntSizeBin(file.zir.string_bytes.len), | |
| 6555 | file.zir.extra.len, fmtIntSizeBin(extra_bytes), | |
| 6543 | file.zir.?.instructions.len, fmtIntSizeBin(instruction_bytes), | |
| 6544 | fmtIntSizeBin(file.zir.?.string_bytes.len), | |
| 6545 | file.zir.?.extra.len, fmtIntSizeBin(extra_bytes), | |
| 6556 | 6546 | }); |
| 6557 | 6547 | // zig fmt: on |
| 6558 | 6548 | } |
| ... | ... | @@ -6586,19 +6576,16 @@ fn cmdChangelist( |
| 6586 | 6576 | |
| 6587 | 6577 | var file: Zcu.File = .{ |
| 6588 | 6578 | .status = .never_loaded, |
| 6589 | .prev_status = .never_loaded, | |
| 6590 | .source_loaded = false, | |
| 6591 | .tree_loaded = false, | |
| 6592 | .zir_loaded = false, | |
| 6593 | 6579 | .sub_file_path = old_source_file, |
| 6594 | .source = undefined, | |
| 6595 | 6580 | .stat = .{ |
| 6596 | 6581 | .size = stat.size, |
| 6597 | 6582 | .inode = stat.inode, |
| 6598 | 6583 | .mtime = stat.mtime, |
| 6599 | 6584 | }, |
| 6600 | .tree = undefined, | |
| 6601 | .zir = undefined, | |
| 6585 | .source = null, | |
| 6586 | .tree = null, | |
| 6587 | .zir = null, | |
| 6588 | .zoir = null, | |
| 6602 | 6589 | .mod = undefined, |
| 6603 | 6590 | }; |
| 6604 | 6591 | |
| ... | ... | @@ -6613,17 +6600,14 @@ fn cmdChangelist( |
| 6613 | 6600 | if (amt != stat.size) |
| 6614 | 6601 | return error.UnexpectedEndOfFile; |
| 6615 | 6602 | file.source = source; |
| 6616 | file.source_loaded = true; | |
| 6617 | 6603 | |
| 6618 | file.tree = try Ast.parse(gpa, file.source, .zig); | |
| 6619 | file.tree_loaded = true; | |
| 6620 | defer file.tree.deinit(gpa); | |
| 6604 | file.tree = try Ast.parse(gpa, file.source.?, .zig); | |
| 6605 | defer file.tree.?.deinit(gpa); | |
| 6621 | 6606 | |
| 6622 | file.zir = try AstGen.generate(gpa, file.tree); | |
| 6623 | file.zir_loaded = true; | |
| 6624 | defer file.zir.deinit(gpa); | |
| 6607 | file.zir = try AstGen.generate(gpa, file.tree.?); | |
| 6608 | defer file.zir.?.deinit(gpa); | |
| 6625 | 6609 | |
| 6626 | if (file.zir.loweringFailed()) { | |
| 6610 | if (file.zir.?.loweringFailed()) { | |
| 6627 | 6611 | var wip_errors: std.zig.ErrorBundle.Wip = undefined; |
| 6628 | 6612 | try wip_errors.init(gpa); |
| 6629 | 6613 | defer wip_errors.deinit(); |
| ... | ... | @@ -6652,13 +6636,12 @@ fn cmdChangelist( |
| 6652 | 6636 | var new_tree = try Ast.parse(gpa, new_source, .zig); |
| 6653 | 6637 | defer new_tree.deinit(gpa); |
| 6654 | 6638 | |
| 6655 | var old_zir = file.zir; | |
| 6639 | var old_zir = file.zir.?; | |
| 6656 | 6640 | defer old_zir.deinit(gpa); |
| 6657 | file.zir_loaded = false; | |
| 6641 | file.zir = null; | |
| 6658 | 6642 | file.zir = try AstGen.generate(gpa, new_tree); |
| 6659 | file.zir_loaded = true; | |
| 6660 | 6643 | |
| 6661 | if (file.zir.loweringFailed()) { | |
| 6644 | if (file.zir.?.loweringFailed()) { | |
| 6662 | 6645 | var wip_errors: std.zig.ErrorBundle.Wip = undefined; |
| 6663 | 6646 | try wip_errors.init(gpa); |
| 6664 | 6647 | defer wip_errors.deinit(); |
| ... | ... | @@ -6672,7 +6655,7 @@ fn cmdChangelist( |
| 6672 | 6655 | var inst_map: std.AutoHashMapUnmanaged(Zir.Inst.Index, Zir.Inst.Index) = .empty; |
| 6673 | 6656 | defer inst_map.deinit(gpa); |
| 6674 | 6657 | |
| 6675 | try Zcu.mapOldZirToNew(gpa, old_zir, file.zir, &inst_map); | |
| 6658 | try Zcu.mapOldZirToNew(gpa, old_zir, file.zir.?, &inst_map); | |
| 6676 | 6659 | |
| 6677 | 6660 | var bw = io.bufferedWriter(io.getStdOut().writer()); |
| 6678 | 6661 | const stdout = bw.writer(); |
src/print_zir.zig+10-13| ... | ... | @@ -22,7 +22,7 @@ pub fn renderAsTextToFile( |
| 22 | 22 | .gpa = gpa, |
| 23 | 23 | .arena = arena.allocator(), |
| 24 | 24 | .file = scope_file, |
| 25 | .code = scope_file.zir, | |
| 25 | .code = scope_file.zir.?, | |
| 26 | 26 | .indent = 0, |
| 27 | 27 | .parent_decl_node = 0, |
| 28 | 28 | .recurse_decls = true, |
| ... | ... | @@ -36,18 +36,18 @@ pub fn renderAsTextToFile( |
| 36 | 36 | try stream.print("%{d} ", .{@intFromEnum(main_struct_inst)}); |
| 37 | 37 | try writer.writeInstToStream(stream, main_struct_inst); |
| 38 | 38 | try stream.writeAll("\n"); |
| 39 | const imports_index = scope_file.zir.extra[@intFromEnum(Zir.ExtraIndex.imports)]; | |
| 39 | const imports_index = scope_file.zir.?.extra[@intFromEnum(Zir.ExtraIndex.imports)]; | |
| 40 | 40 | if (imports_index != 0) { |
| 41 | 41 | try stream.writeAll("Imports:\n"); |
| 42 | 42 | |
| 43 | const extra = scope_file.zir.extraData(Zir.Inst.Imports, imports_index); | |
| 43 | const extra = scope_file.zir.?.extraData(Zir.Inst.Imports, imports_index); | |
| 44 | 44 | var extra_index = extra.end; |
| 45 | 45 | |
| 46 | 46 | for (0..extra.data.imports_len) |_| { |
| 47 | const item = scope_file.zir.extraData(Zir.Inst.Imports.Item, extra_index); | |
| 47 | const item = scope_file.zir.?.extraData(Zir.Inst.Imports.Item, extra_index); | |
| 48 | 48 | extra_index = item.end; |
| 49 | 49 | |
| 50 | const import_path = scope_file.zir.nullTerminatedString(item.data.name); | |
| 50 | const import_path = scope_file.zir.?.nullTerminatedString(item.data.name); | |
| 51 | 51 | try stream.print(" @import(\"{}\") ", .{ |
| 52 | 52 | std.zig.fmtEscapes(import_path), |
| 53 | 53 | }); |
| ... | ... | @@ -75,7 +75,7 @@ pub fn renderInstructionContext( |
| 75 | 75 | .gpa = gpa, |
| 76 | 76 | .arena = arena.allocator(), |
| 77 | 77 | .file = scope_file, |
| 78 | .code = scope_file.zir, | |
| 78 | .code = scope_file.zir.?, | |
| 79 | 79 | .indent = if (indent < 2) 2 else indent, |
| 80 | 80 | .parent_decl_node = parent_decl_node, |
| 81 | 81 | .recurse_decls = false, |
| ... | ... | @@ -107,7 +107,7 @@ pub fn renderSingleInstruction( |
| 107 | 107 | .gpa = gpa, |
| 108 | 108 | .arena = arena.allocator(), |
| 109 | 109 | .file = scope_file, |
| 110 | .code = scope_file.zir, | |
| 110 | .code = scope_file.zir.?, | |
| 111 | 111 | .indent = indent, |
| 112 | 112 | .parent_decl_node = parent_decl_node, |
| 113 | 113 | .recurse_decls = false, |
| ... | ... | @@ -2759,8 +2759,7 @@ const Writer = struct { |
| 2759 | 2759 | } |
| 2760 | 2760 | |
| 2761 | 2761 | fn writeSrcNode(self: *Writer, stream: anytype, src_node: i32) !void { |
| 2762 | if (!self.file.tree_loaded) return; | |
| 2763 | const tree = self.file.tree; | |
| 2762 | const tree = self.file.tree orelse return; | |
| 2764 | 2763 | const abs_node = self.relativeToNodeIndex(src_node); |
| 2765 | 2764 | const src_span = tree.nodeToSpan(abs_node); |
| 2766 | 2765 | const start = self.line_col_cursor.find(tree.source, src_span.start); |
| ... | ... | @@ -2772,8 +2771,7 @@ const Writer = struct { |
| 2772 | 2771 | } |
| 2773 | 2772 | |
| 2774 | 2773 | fn writeSrcTok(self: *Writer, stream: anytype, src_tok: u32) !void { |
| 2775 | if (!self.file.tree_loaded) return; | |
| 2776 | const tree = self.file.tree; | |
| 2774 | const tree = self.file.tree orelse return; | |
| 2777 | 2775 | const abs_tok = tree.firstToken(self.parent_decl_node) + src_tok; |
| 2778 | 2776 | const span_start = tree.tokens.items(.start)[abs_tok]; |
| 2779 | 2777 | const span_end = span_start + @as(u32, @intCast(tree.tokenSlice(abs_tok).len)); |
| ... | ... | @@ -2786,8 +2784,7 @@ const Writer = struct { |
| 2786 | 2784 | } |
| 2787 | 2785 | |
| 2788 | 2786 | fn writeSrcTokAbs(self: *Writer, stream: anytype, src_tok: u32) !void { |
| 2789 | if (!self.file.tree_loaded) return; | |
| 2790 | const tree = self.file.tree; | |
| 2787 | const tree = self.file.tree orelse return; | |
| 2791 | 2788 | const span_start = tree.tokens.items(.start)[src_tok]; |
| 2792 | 2789 | const span_end = span_start + @as(u32, @intCast(tree.tokenSlice(src_tok).len)); |
| 2793 | 2790 | const start = self.line_col_cursor.find(tree.source, span_start); |
test/cases/compile_errors/@import_zon_bad_import.zig deleted-9| ... | ... | @@ -1,9 +0,0 @@ |
| 1 | export fn entry() void { | |
| 2 | _ = @import( | |
| 3 | "bogus-does-not-exist.zon", | |
| 4 | ); | |
| 5 | } | |
| 6 | ||
| 7 | // error | |
| 8 | // | |
| 9 | // :3:9: error: unable to open 'bogus-does-not-exist.zon': FileNotFound |
test/incremental/change_zon_file created+46| ... | ... | @@ -0,0 +1,46 @@ |
| 1 | #target=x86_64-linux-selfhosted | |
| 2 | #target=x86_64-linux-cbe | |
| 3 | #target=x86_64-windows-cbe | |
| 4 | //#target=wasm32-wasi-selfhosted | |
| 5 | #update=initial version | |
| 6 | #file=main.zig | |
| 7 | const std = @import("std"); | |
| 8 | const message: []const u8 = @import("message.zon"); | |
| 9 | pub fn main() !void { | |
| 10 | try std.io.getStdOut().writeAll(message); | |
| 11 | } | |
| 12 | #file=message.zon | |
| 13 | "Hello, World!\n" | |
| 14 | #expect_stdout="Hello, World!\n" | |
| 15 | ||
| 16 | #update=change ZON file contents | |
| 17 | #file=message.zon | |
| 18 | "Hello again, World!\n" | |
| 19 | #expect_stdout="Hello again, World!\n" | |
| 20 | ||
| 21 | #update=delete file | |
| 22 | #rm_file=message.zon | |
| 23 | #expect_error=message.zon:1:1: error: unable to load './message.zon': FileNotFound | |
| 24 | ||
| 25 | #update=remove reference to ZON file | |
| 26 | #file=main.zig | |
| 27 | const std = @import("std"); | |
| 28 | const message: []const u8 = @import("message.zon"); | |
| 29 | pub fn main() !void { | |
| 30 | try std.io.getStdOut().writeAll("a hardcoded string\n"); | |
| 31 | } | |
| 32 | #expect_error=message.zon:1:1: error: unable to load './message.zon': FileNotFound | |
| 33 | ||
| 34 | #update=recreate ZON file | |
| 35 | #file=message.zon | |
| 36 | "We're back, World!\n" | |
| 37 | #expect_stdout="a hardcoded string\n" | |
| 38 | ||
| 39 | #update=re-introduce reference to ZON file | |
| 40 | #file=main.zig | |
| 41 | const std = @import("std"); | |
| 42 | const message: []const u8 = @import("message.zon"); | |
| 43 | pub fn main() !void { | |
| 44 | try std.io.getStdOut().writeAll(message); | |
| 45 | } | |
| 46 | #expect_stdout="We're back, World!\n" |