| 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,6 +10,31 @@ string_bytes: []u8, |
| 10 | compile_errors: []Zoir.CompileError, | 10 | compile_errors: []Zoir.CompileError, |
| 11 | error_notes: []Zoir.CompileError.Note, | 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 | pub fn hasCompileErrors(zoir: Zoir) bool { | 38 | pub fn hasCompileErrors(zoir: Zoir) bool { |
| 14 | if (zoir.compile_errors.len > 0) { | 39 | if (zoir.compile_errors.len > 0) { |
| 15 | assert(zoir.nodes.len == 0); | 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,14 +264,12 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void { |
| 264 | } | 264 | } |
| 265 | 265 | ||
| 266 | pub fn populateFile(comp: *Compilation, mod: *Module, file: *File) !void { | 266 | pub fn populateFile(comp: *Compilation, mod: *Module, file: *File) !void { |
| 267 | assert(file.source_loaded == true); | ||
| 268 | |||
| 269 | if (mod.root.statFile(mod.root_src_path)) |stat| { | 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 | std.log.warn( | 269 | std.log.warn( |
| 272 | "the cached file '{}{s}' had the wrong size. Expected {d}, found {d}. " ++ | 270 | "the cached file '{}{s}' had the wrong size. Expected {d}, found {d}. " ++ |
| 273 | "Overwriting with correct file contents now", | 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 | try writeFile(file, mod); | 275 | try writeFile(file, mod); |
| ... | @@ -296,15 +294,13 @@ pub fn populateFile(comp: *Compilation, mod: *Module, file: *File) !void { | ... | @@ -296,15 +294,13 @@ pub fn populateFile(comp: *Compilation, mod: *Module, file: *File) !void { |
| 296 | 294 | ||
| 297 | log.debug("parsing and generating '{s}'", .{mod.root_src_path}); | 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); | 297 | file.tree = try std.zig.Ast.parse(comp.gpa, file.source.?, .zig); |
| 300 | assert(file.tree.errors.len == 0); // builtin.zig must parse | 298 | assert(file.tree.?.errors.len == 0); // builtin.zig must parse |
| 301 | file.tree_loaded = true; | ||
| 302 | 299 | ||
| 303 | file.zir = try AstGen.generate(comp.gpa, file.tree); | 300 | file.zir = try AstGen.generate(comp.gpa, file.tree.?); |
| 304 | assert(!file.zir.hasCompileErrors()); // builtin.zig must not have astgen errors | 301 | assert(!file.zir.?.hasCompileErrors()); // builtin.zig must not have astgen errors |
| 305 | file.zir_loaded = true; | 302 | file.status = .success; |
| 306 | file.status = .success_zir; | 303 | // Note that whilst we set `zir` here, we populated `path_digest` |
| 307 | // Note that whilst we set `zir_loaded` here, we populated `path_digest` | ||
| 308 | // all the way back in `Package.Module.create`. | 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,7 +308,7 @@ fn writeFile(file: *File, mod: *Module) !void { |
| 312 | var buf: [std.fs.max_path_bytes]u8 = undefined; | 308 | var buf: [std.fs.max_path_bytes]u8 = undefined; |
| 313 | var af = try mod.root.atomicFile(mod.root_src_path, .{ .make_path = true }, &buf); | 309 | var af = try mod.root.atomicFile(mod.root_src_path, .{ .make_path = true }, &buf); |
| 314 | defer af.deinit(); | 310 | defer af.deinit(); |
| 315 | try af.file.writeAll(file.source); | 311 | try af.file.writeAll(file.source.?); |
| 316 | af.finish() catch |err| switch (err) { | 312 | af.finish() catch |err| switch (err) { |
| 317 | error.AccessDenied => switch (builtin.os.tag) { | 313 | error.AccessDenied => switch (builtin.os.tag) { |
| 318 | .windows => { | 314 | .windows => { |
| ... | @@ -326,7 +322,7 @@ fn writeFile(file: *File, mod: *Module) !void { | ... | @@ -326,7 +322,7 @@ fn writeFile(file: *File, mod: *Module) !void { |
| 326 | }; | 322 | }; |
| 327 | 323 | ||
| 328 | file.stat = .{ | 324 | file.stat = .{ |
| 329 | .size = file.source.len, | 325 | .size = file.source.?.len, |
| 330 | .inode = 0, // dummy value | 326 | .inode = 0, // dummy value |
| 331 | .mtime = 0, // dummy value | 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,10 +2220,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void { |
| 2220 | try comp.astgen_work_queue.ensureUnusedCapacity(zcu.import_table.count()); | 2220 | try comp.astgen_work_queue.ensureUnusedCapacity(zcu.import_table.count()); |
| 2221 | for (zcu.import_table.values()) |file_index| { | 2221 | for (zcu.import_table.values()) |file_index| { |
| 2222 | if (zcu.fileByIndex(file_index).mod.isBuiltin()) continue; | 2222 | if (zcu.fileByIndex(file_index).mod.isBuiltin()) continue; |
| 2223 | const file = zcu.fileByIndex(file_index); | 2223 | comp.astgen_work_queue.writeItemAssumeCapacity(file_index); |
| 2224 | if (file.getMode() == .zig) { | ||
| 2225 | comp.astgen_work_queue.writeItemAssumeCapacity(file_index); | ||
| 2226 | } | ||
| 2227 | } | 2224 | } |
| 2228 | if (comp.file_system_inputs) |fsi| { | 2225 | if (comp.file_system_inputs) |fsi| { |
| 2229 | for (zcu.import_table.values()) |file_index| { | 2226 | for (zcu.import_table.values()) |file_index| { |
| ... | @@ -2906,10 +2903,12 @@ pub fn makeBinFileWritable(comp: *Compilation) !void { | ... | @@ -2906,10 +2903,12 @@ pub fn makeBinFileWritable(comp: *Compilation) !void { |
| 2906 | const Header = extern struct { | 2903 | const Header = extern struct { |
| 2907 | intern_pool: extern struct { | 2904 | intern_pool: extern struct { |
| 2908 | thread_count: u32, | 2905 | thread_count: u32, |
| 2909 | file_deps_len: u32, | ||
| 2910 | src_hash_deps_len: u32, | 2906 | src_hash_deps_len: u32, |
| 2911 | nav_val_deps_len: u32, | 2907 | nav_val_deps_len: u32, |
| 2912 | nav_ty_deps_len: u32, | 2908 | nav_ty_deps_len: u32, |
| 2909 | interned_deps_len: u32, | ||
| 2910 | zon_file_deps_len: u32, | ||
| 2911 | embed_file_deps_len: u32, | ||
| 2913 | namespace_deps_len: u32, | 2912 | namespace_deps_len: u32, |
| 2914 | namespace_name_deps_len: u32, | 2913 | namespace_name_deps_len: u32, |
| 2915 | first_dependency_len: u32, | 2914 | first_dependency_len: u32, |
| ... | @@ -2950,10 +2949,12 @@ pub fn saveState(comp: *Compilation) !void { | ... | @@ -2950,10 +2949,12 @@ pub fn saveState(comp: *Compilation) !void { |
| 2950 | const header: Header = .{ | 2949 | const header: Header = .{ |
| 2951 | .intern_pool = .{ | 2950 | .intern_pool = .{ |
| 2952 | .thread_count = @intCast(ip.locals.len), | 2951 | .thread_count = @intCast(ip.locals.len), |
| 2953 | .file_deps_len = @intCast(ip.file_deps.count()), | ||
| 2954 | .src_hash_deps_len = @intCast(ip.src_hash_deps.count()), | 2952 | .src_hash_deps_len = @intCast(ip.src_hash_deps.count()), |
| 2955 | .nav_val_deps_len = @intCast(ip.nav_val_deps.count()), | 2953 | .nav_val_deps_len = @intCast(ip.nav_val_deps.count()), |
| 2956 | .nav_ty_deps_len = @intCast(ip.nav_ty_deps.count()), | 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 | .namespace_deps_len = @intCast(ip.namespace_deps.count()), | 2958 | .namespace_deps_len = @intCast(ip.namespace_deps.count()), |
| 2958 | .namespace_name_deps_len = @intCast(ip.namespace_name_deps.count()), | 2959 | .namespace_name_deps_len = @intCast(ip.namespace_name_deps.count()), |
| 2959 | .first_dependency_len = @intCast(ip.first_dependency.count()), | 2960 | .first_dependency_len = @intCast(ip.first_dependency.count()), |
| ... | @@ -2978,14 +2979,18 @@ pub fn saveState(comp: *Compilation) !void { | ... | @@ -2978,14 +2979,18 @@ pub fn saveState(comp: *Compilation) !void { |
| 2978 | addBuf(&bufs, mem.asBytes(&header)); | 2979 | addBuf(&bufs, mem.asBytes(&header)); |
| 2979 | addBuf(&bufs, mem.sliceAsBytes(pt_headers.items)); | 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 | addBuf(&bufs, mem.sliceAsBytes(ip.src_hash_deps.keys())); | 2982 | addBuf(&bufs, mem.sliceAsBytes(ip.src_hash_deps.keys())); |
| 2984 | addBuf(&bufs, mem.sliceAsBytes(ip.src_hash_deps.values())); | 2983 | addBuf(&bufs, mem.sliceAsBytes(ip.src_hash_deps.values())); |
| 2985 | addBuf(&bufs, mem.sliceAsBytes(ip.nav_val_deps.keys())); | 2984 | addBuf(&bufs, mem.sliceAsBytes(ip.nav_val_deps.keys())); |
| 2986 | addBuf(&bufs, mem.sliceAsBytes(ip.nav_val_deps.values())); | 2985 | addBuf(&bufs, mem.sliceAsBytes(ip.nav_val_deps.values())); |
| 2987 | addBuf(&bufs, mem.sliceAsBytes(ip.nav_ty_deps.keys())); | 2986 | addBuf(&bufs, mem.sliceAsBytes(ip.nav_ty_deps.keys())); |
| 2988 | addBuf(&bufs, mem.sliceAsBytes(ip.nav_ty_deps.values())); | 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 | addBuf(&bufs, mem.sliceAsBytes(ip.namespace_deps.keys())); | 2994 | addBuf(&bufs, mem.sliceAsBytes(ip.namespace_deps.keys())); |
| 2990 | addBuf(&bufs, mem.sliceAsBytes(ip.namespace_deps.values())); | 2995 | addBuf(&bufs, mem.sliceAsBytes(ip.namespace_deps.values())); |
| 2991 | addBuf(&bufs, mem.sliceAsBytes(ip.namespace_name_deps.keys())); | 2996 | addBuf(&bufs, mem.sliceAsBytes(ip.namespace_name_deps.keys())); |
| ... | @@ -3203,15 +3208,13 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle { | ... | @@ -3203,15 +3208,13 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle { |
| 3203 | } | 3208 | } |
| 3204 | 3209 | ||
| 3205 | if (comp.zcu) |zcu| { | 3210 | if (comp.zcu) |zcu| { |
| 3206 | const ip = &zcu.intern_pool; | ||
| 3207 | |||
| 3208 | for (zcu.failed_files.keys(), zcu.failed_files.values()) |file, error_msg| { | 3211 | for (zcu.failed_files.keys(), zcu.failed_files.values()) |file, error_msg| { |
| 3209 | if (error_msg) |msg| { | 3212 | if (error_msg) |msg| { |
| 3210 | try addModuleErrorMsg(zcu, &bundle, msg.*); | 3213 | try addModuleErrorMsg(zcu, &bundle, msg.*); |
| 3211 | } else { | 3214 | } else { |
| 3212 | // Must be ZIR or Zoir errors. Note that this may include AST errors. | 3215 | // Must be ZIR or Zoir errors. Note that this may include AST errors. |
| 3213 | _ = try file.getTree(gpa); // Tree must be loaded. | 3216 | _ = try file.getTree(gpa); // Tree must be loaded. |
| 3214 | if (file.zir_loaded) { | 3217 | if (file.zir != null) { |
| 3215 | try addZirErrorMessages(&bundle, file); | 3218 | try addZirErrorMessages(&bundle, file); |
| 3216 | } else if (file.zoir != null) { | 3219 | } else if (file.zoir != null) { |
| 3217 | try addZoirErrorMessages(&bundle, file); | 3220 | try addZoirErrorMessages(&bundle, file); |
| ... | @@ -3277,20 +3280,6 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle { | ... | @@ -3277,20 +3280,6 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle { |
| 3277 | if (!refs.contains(anal_unit)) continue; | 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 | std.log.scoped(.zcu).debug("analysis error '{s}' reported from unit '{}'", .{ | 3283 | std.log.scoped(.zcu).debug("analysis error '{s}' reported from unit '{}'", .{ |
| 3295 | error_msg.msg, | 3284 | error_msg.msg, |
| 3296 | zcu.fmtAnalUnit(anal_unit), | 3285 | zcu.fmtAnalUnit(anal_unit), |
| ... | @@ -3318,12 +3307,10 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle { | ... | @@ -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| { | 3310 | for (zcu.failed_codegen.values()) |error_msg| { |
| 3322 | if (!zcu.navFileScope(nav).okToReportErrors()) continue; | ||
| 3323 | try addModuleErrorMsg(zcu, &bundle, error_msg.*); | 3311 | try addModuleErrorMsg(zcu, &bundle, error_msg.*); |
| 3324 | } | 3312 | } |
| 3325 | for (zcu.failed_types.keys(), zcu.failed_types.values()) |ty_index, error_msg| { | 3313 | for (zcu.failed_types.values()) |error_msg| { |
| 3326 | if (!zcu.typeFileScope(ty_index).okToReportErrors()) continue; | ||
| 3327 | try addModuleErrorMsg(zcu, &bundle, error_msg.*); | 3314 | try addModuleErrorMsg(zcu, &bundle, error_msg.*); |
| 3328 | } | 3315 | } |
| 3329 | for (zcu.failed_exports.values()) |value| { | 3316 | for (zcu.failed_exports.values()) |value| { |
| ... | @@ -3623,22 +3610,17 @@ pub fn addModuleErrorMsg( | ... | @@ -3623,22 +3610,17 @@ pub fn addModuleErrorMsg( |
| 3623 | } | 3610 | } |
| 3624 | 3611 | ||
| 3625 | pub fn addZirErrorMessages(eb: *ErrorBundle.Wip, file: *Zcu.File) !void { | 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 | const gpa = eb.gpa; | 3613 | const gpa = eb.gpa; |
| 3630 | const src_path = try file.fullPath(gpa); | 3614 | const src_path = try file.fullPath(gpa); |
| 3631 | defer gpa.free(src_path); | 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 | pub fn addZoirErrorMessages(eb: *ErrorBundle.Wip, file: *Zcu.File) !void { | 3619 | pub fn addZoirErrorMessages(eb: *ErrorBundle.Wip, file: *Zcu.File) !void { |
| 3636 | assert(file.source_loaded); | ||
| 3637 | assert(file.tree_loaded); | ||
| 3638 | const gpa = eb.gpa; | 3620 | const gpa = eb.gpa; |
| 3639 | const src_path = try file.fullPath(gpa); | 3621 | const src_path = try file.fullPath(gpa); |
| 3640 | defer gpa.free(src_path); | 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 | pub fn performAllTheWork( | 3626 | pub fn performAllTheWork( |
| ... | @@ -3802,7 +3784,7 @@ fn performAllTheWorkInner( | ... | @@ -3802,7 +3784,7 @@ fn performAllTheWorkInner( |
| 3802 | // will be needed by the worker threads. | 3784 | // will be needed by the worker threads. |
| 3803 | const path_digest = zcu.filePathDigest(file_index); | 3785 | const path_digest = zcu.filePathDigest(file_index); |
| 3804 | const file = zcu.fileByIndex(file_index); | 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 | comp, file, file_index, path_digest, zir_prog_node, &astgen_wait_group, .root, | 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,7 +3792,7 @@ fn performAllTheWorkInner( |
| 3810 | 3792 | ||
| 3811 | for (0.., zcu.embed_table.values()) |ef_index_usize, ef| { | 3793 | for (0.., zcu.embed_table.values()) |ef_index_usize, ef| { |
| 3812 | const ef_index: Zcu.EmbedFile.Index = @enumFromInt(ef_index_usize); | 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 | comp, ef_index, ef, | 3796 | comp, ef_index, ef, |
| 3815 | }); | 3797 | }); |
| 3816 | } | 3798 | } |
| ... | @@ -3832,12 +3814,64 @@ fn performAllTheWorkInner( | ... | @@ -3832,12 +3814,64 @@ fn performAllTheWorkInner( |
| 3832 | if (comp.zcu) |zcu| { | 3814 | if (comp.zcu) |zcu| { |
| 3833 | const pt: Zcu.PerThread = .activate(zcu, .main); | 3815 | const pt: Zcu.PerThread = .activate(zcu, .main); |
| 3834 | defer pt.deactivate(); | 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 | if (comp.incremental) { | 3870 | if (comp.incremental) { |
| 3836 | const update_zir_refs_node = main_progress_node.start("Update ZIR References", 0); | 3871 | const update_zir_refs_node = main_progress_node.start("Update ZIR References", 0); |
| 3837 | defer update_zir_refs_node.end(); | 3872 | defer update_zir_refs_node.end(); |
| 3838 | try pt.updateZirRefs(); | 3873 | try pt.updateZirRefs(); |
| 3839 | } | 3874 | } |
| 3840 | try reportMultiModuleErrors(pt); | ||
| 3841 | try zcu.flushRetryableFailures(); | 3875 | try zcu.flushRetryableFailures(); |
| 3842 | 3876 | ||
| 3843 | zcu.sema_prog_node = main_progress_node.start("Semantic Analysis", 0); | 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,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 | tid: usize, | 4318 | tid: usize, |
| 4285 | comp: *Compilation, | 4319 | comp: *Compilation, |
| 4286 | file: *Zcu.File, | 4320 | file: *Zcu.File, |
| ... | @@ -4290,40 +4324,44 @@ fn workerAstGenFile( | ... | @@ -4290,40 +4324,44 @@ fn workerAstGenFile( |
| 4290 | wg: *WaitGroup, | 4324 | wg: *WaitGroup, |
| 4291 | src: Zcu.AstGenSrc, | 4325 | src: Zcu.AstGenSrc, |
| 4292 | ) void { | 4326 | ) void { |
| 4293 | assert(file.getMode() == .zig); | ||
| 4294 | const child_prog_node = prog_node.start(file.sub_file_path, 0); | 4327 | const child_prog_node = prog_node.start(file.sub_file_path, 0); |
| 4295 | defer child_prog_node.end(); | 4328 | defer child_prog_node.end(); |
| 4296 | 4329 | ||
| 4297 | const pt: Zcu.PerThread = .activate(comp.zcu.?, @enumFromInt(tid)); | 4330 | const pt: Zcu.PerThread = .activate(comp.zcu.?, @enumFromInt(tid)); |
| 4298 | defer pt.deactivate(); | 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 | error.AnalysisFail => return, | 4333 | error.AnalysisFail => return, |
| 4301 | else => { | 4334 | else => { |
| 4302 | file.status = .retryable_failure; | ||
| 4303 | pt.reportRetryableAstGenError(src, file_index, err) catch |oom| switch (oom) { | 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 | 4336 | error.OutOfMemory => { |
| 4305 | // there is a missing `failed_files` error message. | 4337 | comp.mutex.lock(); |
| 4306 | error.OutOfMemory => {}, | 4338 | defer comp.mutex.unlock(); |
| 4339 | comp.setAllocFailure(); | ||
| 4340 | }, | ||
| 4307 | }; | 4341 | }; |
| 4308 | return; | 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 | // Pre-emptively look for `@import` paths and queue them up. | 4351 | // Pre-emptively look for `@import` paths and queue them up. |
| 4313 | // If we experience an error preemptively fetching the | 4352 | // If we experience an error preemptively fetching the |
| 4314 | // file, just ignore it and let it happen again later during Sema. | 4353 | // file, just ignore it and let it happen again later during Sema. |
| 4315 | assert(file.zir_loaded); | 4354 | const imports_index = file.zir.?.extra[@intFromEnum(Zir.ExtraIndex.imports)]; |
| 4316 | const imports_index = file.zir.extra[@intFromEnum(Zir.ExtraIndex.imports)]; | ||
| 4317 | if (imports_index != 0) { | 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 | var import_i: u32 = 0; | 4357 | var import_i: u32 = 0; |
| 4320 | var extra_index = extra.end; | 4358 | var extra_index = extra.end; |
| 4321 | 4359 | ||
| 4322 | while (import_i < extra.data.imports_len) : (import_i += 1) { | 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 | extra_index = item.end; | 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 | // `@import("builtin")` is handled specially. | 4365 | // `@import("builtin")` is handled specially. |
| 4328 | if (mem.eql(u8, import_path, "builtin")) continue; | 4366 | if (mem.eql(u8, import_path, "builtin")) continue; |
| 4329 | 4367 | ||
| ... | @@ -4344,7 +4382,7 @@ fn workerAstGenFile( | ... | @@ -4344,7 +4382,7 @@ fn workerAstGenFile( |
| 4344 | const imported_path_digest = pt.zcu.filePathDigest(res.file_index); | 4382 | const imported_path_digest = pt.zcu.filePathDigest(res.file_index); |
| 4345 | break :blk .{ res, imported_path_digest }; | 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 | log.debug("AstGen of {s} has import '{s}'; queuing AstGen of {s}", .{ | 4386 | log.debug("AstGen of {s} has import '{s}'; queuing AstGen of {s}", .{ |
| 4349 | file.sub_file_path, import_path, import_result.file.sub_file_path, | 4387 | file.sub_file_path, import_path, import_result.file.sub_file_path, |
| 4350 | }); | 4388 | }); |
| ... | @@ -4352,7 +4390,7 @@ fn workerAstGenFile( | ... | @@ -4352,7 +4390,7 @@ fn workerAstGenFile( |
| 4352 | .importing_file = file_index, | 4390 | .importing_file = file_index, |
| 4353 | .import_tok = item.data.token, | 4391 | .import_tok = item.data.token, |
| 4354 | } }; | 4392 | } }; |
| 4355 | comp.thread_pool.spawnWgId(wg, workerAstGenFile, .{ | 4393 | comp.thread_pool.spawnWgId(wg, workerUpdateFile, .{ |
| 4356 | comp, import_result.file, import_result.file_index, imported_path_digest, prog_node, wg, sub_src, | 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,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 | comp.detectEmbedFileUpdate(@enumFromInt(tid), ef_index, ef) catch |err| switch (err) { | 4417 | comp.detectEmbedFileUpdate(@enumFromInt(tid), ef_index, ef) catch |err| switch (err) { |
| 4380 | error.OutOfMemory => { | 4418 | error.OutOfMemory => { |
| 4381 | comp.mutex.lock(); | 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,13 +17,6 @@ tid_shift_31: if (single_threaded) u0 else std.math.Log2Int(u32), |
| 17 | /// Cached shift amount to put a `tid` in the top bits of a 32-bit value. | 17 | /// Cached shift amount to put a `tid` in the top bits of a 32-bit value. |
| 18 | tid_shift_32: if (single_threaded) u0 else std.math.Log2Int(u32), | 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 | /// Dependencies on the source code hash associated with a ZIR instruction. | 20 | /// Dependencies on the source code hash associated with a ZIR instruction. |
| 28 | /// * For a `declaration`, this is the entire declaration body. | 21 | /// * For a `declaration`, this is the entire declaration body. |
| 29 | /// * For a `struct_decl`, `union_decl`, etc, this is the source of the fields (but not declarations). | 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,6 +35,9 @@ nav_ty_deps: std.AutoArrayHashMapUnmanaged(Nav.Index, DepEntry.Index), |
| 42 | /// * a container type requiring resolution (invalidated when the type must be recreated at a new index) | 35 | /// * a container type requiring resolution (invalidated when the type must be recreated at a new index) |
| 43 | /// Value is index into `dep_entries` of the first dependency on this interned value. | 36 | /// Value is index into `dep_entries` of the first dependency on this interned value. |
| 44 | interned_deps: std.AutoArrayHashMapUnmanaged(Index, DepEntry.Index), | 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 | /// Dependencies on an embedded file. | 41 | /// Dependencies on an embedded file. |
| 46 | /// Introduced by `@embedFile`; invalidated when the file changes. | 42 | /// Introduced by `@embedFile`; invalidated when the file changes. |
| 47 | /// Value is index into `dep_entries` of the first dependency on this `Zcu.EmbedFile`. | 43 | /// Value is index into `dep_entries` of the first dependency on this `Zcu.EmbedFile`. |
| ... | @@ -89,11 +85,11 @@ pub const empty: InternPool = .{ | ... | @@ -89,11 +85,11 @@ pub const empty: InternPool = .{ |
| 89 | .tid_shift_30 = if (single_threaded) 0 else 31, | 85 | .tid_shift_30 = if (single_threaded) 0 else 31, |
| 90 | .tid_shift_31 = if (single_threaded) 0 else 31, | 86 | .tid_shift_31 = if (single_threaded) 0 else 31, |
| 91 | .tid_shift_32 = if (single_threaded) 0 else 31, | 87 | .tid_shift_32 = if (single_threaded) 0 else 31, |
| 92 | .file_deps = .empty, | ||
| 93 | .src_hash_deps = .empty, | 88 | .src_hash_deps = .empty, |
| 94 | .nav_val_deps = .empty, | 89 | .nav_val_deps = .empty, |
| 95 | .nav_ty_deps = .empty, | 90 | .nav_ty_deps = .empty, |
| 96 | .interned_deps = .empty, | 91 | .interned_deps = .empty, |
| 92 | .zon_file_deps = .empty, | ||
| 97 | .embed_file_deps = .empty, | 93 | .embed_file_deps = .empty, |
| 98 | .namespace_deps = .empty, | 94 | .namespace_deps = .empty, |
| 99 | .namespace_name_deps = .empty, | 95 | .namespace_name_deps = .empty, |
| ... | @@ -824,11 +820,11 @@ pub const Nav = struct { | ... | @@ -824,11 +820,11 @@ pub const Nav = struct { |
| 824 | }; | 820 | }; |
| 825 | 821 | ||
| 826 | pub const Dependee = union(enum) { | 822 | pub const Dependee = union(enum) { |
| 827 | file: FileIndex, | ||
| 828 | src_hash: TrackedInst.Index, | 823 | src_hash: TrackedInst.Index, |
| 829 | nav_val: Nav.Index, | 824 | nav_val: Nav.Index, |
| 830 | nav_ty: Nav.Index, | 825 | nav_ty: Nav.Index, |
| 831 | interned: Index, | 826 | interned: Index, |
| 827 | zon_file: FileIndex, | ||
| 832 | embed_file: Zcu.EmbedFile.Index, | 828 | embed_file: Zcu.EmbedFile.Index, |
| 833 | namespace: TrackedInst.Index, | 829 | namespace: TrackedInst.Index, |
| 834 | namespace_name: NamespaceNameKey, | 830 | namespace_name: NamespaceNameKey, |
| ... | @@ -876,11 +872,11 @@ pub const DependencyIterator = struct { | ... | @@ -876,11 +872,11 @@ pub const DependencyIterator = struct { |
| 876 | 872 | ||
| 877 | pub fn dependencyIterator(ip: *const InternPool, dependee: Dependee) DependencyIterator { | 873 | pub fn dependencyIterator(ip: *const InternPool, dependee: Dependee) DependencyIterator { |
| 878 | const first_entry = switch (dependee) { | 874 | const first_entry = switch (dependee) { |
| 879 | .file => |x| ip.file_deps.get(x), | ||
| 880 | .src_hash => |x| ip.src_hash_deps.get(x), | 875 | .src_hash => |x| ip.src_hash_deps.get(x), |
| 881 | .nav_val => |x| ip.nav_val_deps.get(x), | 876 | .nav_val => |x| ip.nav_val_deps.get(x), |
| 882 | .nav_ty => |x| ip.nav_ty_deps.get(x), | 877 | .nav_ty => |x| ip.nav_ty_deps.get(x), |
| 883 | .interned => |x| ip.interned_deps.get(x), | 878 | .interned => |x| ip.interned_deps.get(x), |
| 879 | .zon_file => |x| ip.zon_file_deps.get(x), | ||
| 884 | .embed_file => |x| ip.embed_file_deps.get(x), | 880 | .embed_file => |x| ip.embed_file_deps.get(x), |
| 885 | .namespace => |x| ip.namespace_deps.get(x), | 881 | .namespace => |x| ip.namespace_deps.get(x), |
| 886 | .namespace_name => |x| ip.namespace_name_deps.get(x), | 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,11 +943,11 @@ pub fn addDependency(ip: *InternPool, gpa: Allocator, depender: AnalUnit, depend |
| 947 | }, | 943 | }, |
| 948 | inline else => |dependee_payload, tag| new_index: { | 944 | inline else => |dependee_payload, tag| new_index: { |
| 949 | const gop = try switch (tag) { | 945 | const gop = try switch (tag) { |
| 950 | .file => ip.file_deps, | ||
| 951 | .src_hash => ip.src_hash_deps, | 946 | .src_hash => ip.src_hash_deps, |
| 952 | .nav_val => ip.nav_val_deps, | 947 | .nav_val => ip.nav_val_deps, |
| 953 | .nav_ty => ip.nav_ty_deps, | 948 | .nav_ty => ip.nav_ty_deps, |
| 954 | .interned => ip.interned_deps, | 949 | .interned => ip.interned_deps, |
| 950 | .zon_file => ip.zon_file_deps, | ||
| 955 | .embed_file => ip.embed_file_deps, | 951 | .embed_file => ip.embed_file_deps, |
| 956 | .namespace => ip.namespace_deps, | 952 | .namespace => ip.namespace_deps, |
| 957 | .namespace_name => ip.namespace_name_deps, | 953 | .namespace_name => ip.namespace_name_deps, |
| ... | @@ -6688,11 +6684,11 @@ pub fn init(ip: *InternPool, gpa: Allocator, available_threads: usize) !void { | ... | @@ -6688,11 +6684,11 @@ pub fn init(ip: *InternPool, gpa: Allocator, available_threads: usize) !void { |
| 6688 | pub fn deinit(ip: *InternPool, gpa: Allocator) void { | 6684 | pub fn deinit(ip: *InternPool, gpa: Allocator) void { |
| 6689 | if (debug_state.enable_checks) std.debug.assert(debug_state.intern_pool == null); | 6685 | if (debug_state.enable_checks) std.debug.assert(debug_state.intern_pool == null); |
| 6690 | 6686 | ||
| 6691 | ip.file_deps.deinit(gpa); | ||
| 6692 | ip.src_hash_deps.deinit(gpa); | 6687 | ip.src_hash_deps.deinit(gpa); |
| 6693 | ip.nav_val_deps.deinit(gpa); | 6688 | ip.nav_val_deps.deinit(gpa); |
| 6694 | ip.nav_ty_deps.deinit(gpa); | 6689 | ip.nav_ty_deps.deinit(gpa); |
| 6695 | ip.interned_deps.deinit(gpa); | 6690 | ip.interned_deps.deinit(gpa); |
| 6691 | ip.zon_file_deps.deinit(gpa); | ||
| 6696 | ip.embed_file_deps.deinit(gpa); | 6692 | ip.embed_file_deps.deinit(gpa); |
| 6697 | ip.namespace_deps.deinit(gpa); | 6693 | ip.namespace_deps.deinit(gpa); |
| 6698 | ip.namespace_name_deps.deinit(gpa); | 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,15 +482,12 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Package.Module { |
| 482 | }; | 482 | }; |
| 483 | new_file.* = .{ | 483 | new_file.* = .{ |
| 484 | .sub_file_path = "builtin.zig", | 484 | .sub_file_path = "builtin.zig", |
| 485 | .source = generated_builtin_source, | ||
| 486 | .source_loaded = true, | ||
| 487 | .tree_loaded = false, | ||
| 488 | .zir_loaded = false, | ||
| 489 | .stat = undefined, | 485 | .stat = undefined, |
| 490 | .tree = undefined, | 486 | .source = generated_builtin_source, |
| 491 | .zir = undefined, | 487 | .tree = null, |
| 488 | .zir = null, | ||
| 489 | .zoir = null, | ||
| 492 | .status = .never_loaded, | 490 | .status = .never_loaded, |
| 493 | .prev_status = .never_loaded, | ||
| 494 | .mod = new, | 491 | .mod = new, |
| 495 | }; | 492 | }; |
| 496 | break :b new; | 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,10 +6140,9 @@ fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileEr |
| 6140 | return sema.fail(&child_block, src, "C import failed: {s}", .{@errorName(err)}); | 6140 | return sema.fail(&child_block, src, "C import failed: {s}", .{@errorName(err)}); |
| 6141 | 6141 | ||
| 6142 | const path_digest = zcu.filePathDigest(result.file_index); | 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 | return sema.fail(&child_block, src, "C import failed: {s}", .{@errorName(err)}); | 6144 | return sema.fail(&child_block, src, "C import failed: {s}", .{@errorName(err)}); |
| 6145 | 6145 | ||
| 6146 | try sema.declareDependency(.{ .file = result.file_index }); | ||
| 6147 | try pt.ensureFileAnalyzed(result.file_index); | 6146 | try pt.ensureFileAnalyzed(result.file_index); |
| 6148 | const ty = zcu.fileRootType(result.file_index); | 6147 | const ty = zcu.fileRootType(result.file_index); |
| 6149 | try sema.declareDependency(.{ .interned = ty }); | 6148 | try sema.declareDependency(.{ .interned = ty }); |
| ... | @@ -7649,9 +7648,8 @@ fn analyzeCall( | ... | @@ -7649,9 +7648,8 @@ fn analyzeCall( |
| 7649 | const nav = ip.getNav(info.owner_nav); | 7648 | const nav = ip.getNav(info.owner_nav); |
| 7650 | const resolved_func_inst = info.zir_body_inst.resolveFull(ip) orelse return error.AnalysisFail; | 7649 | const resolved_func_inst = info.zir_body_inst.resolveFull(ip) orelse return error.AnalysisFail; |
| 7651 | const file = zcu.fileByIndex(resolved_func_inst.file); | 7650 | const file = zcu.fileByIndex(resolved_func_inst.file); |
| 7652 | assert(file.zir_loaded); | 7651 | const zir_info = file.zir.?.getFnInfo(resolved_func_inst.inst); |
| 7653 | 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 }; |
| 7654 | break :b .{ nav, file.zir, info.zir_body_inst, resolved_func_inst.inst, zir_info }; | ||
| 7655 | } else .{ undefined, undefined, undefined, undefined, undefined }; | 7653 | } else .{ undefined, undefined, undefined, undefined, undefined }; |
| 7656 | 7654 | ||
| 7657 | // This is the `inst_map` used when evaluating generic parameters and return types. | 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,7 +13985,6 @@ fn zirImport(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. |
| 13987 | }; | 13985 | }; |
| 13988 | switch (result.file.getMode()) { | 13986 | switch (result.file.getMode()) { |
| 13989 | .zig => { | 13987 | .zig => { |
| 13990 | try sema.declareDependency(.{ .file = result.file_index }); | ||
| 13991 | try pt.ensureFileAnalyzed(result.file_index); | 13988 | try pt.ensureFileAnalyzed(result.file_index); |
| 13992 | const ty = zcu.fileRootType(result.file_index); | 13989 | const ty = zcu.fileRootType(result.file_index); |
| 13993 | try sema.declareDependency(.{ .interned = ty }); | 13990 | try sema.declareDependency(.{ .interned = ty }); |
| ... | @@ -13995,12 +13992,6 @@ fn zirImport(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. | ... | @@ -13995,12 +13992,6 @@ fn zirImport(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. |
| 13995 | return Air.internedToRef(ty); | 13992 | return Air.internedToRef(ty); |
| 13996 | }, | 13993 | }, |
| 13997 | .zon => { | 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 | if (extra.res_ty == .none) { | 13995 | if (extra.res_ty == .none) { |
| 14005 | return sema.fail(block, operand_src, "'@import' of ZON must have a known result type", .{}); | 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,6 +14001,7 @@ fn zirImport(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. |
| 14010 | return sema.fail(block, operand_src, "'@import' of ZON must have a known result type", .{}); | 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 | const interned = try LowerZon.run( | 14005 | const interned = try LowerZon.run( |
| 14014 | sema, | 14006 | sema, |
| 14015 | result.file, | 14007 | result.file, |
| ... | @@ -35328,7 +35320,7 @@ fn backingIntType( | ... | @@ -35328,7 +35320,7 @@ fn backingIntType( |
| 35328 | break :blk accumulator; | 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 | const zir_index = struct_type.zir_index.resolve(ip) orelse return error.AnalysisFail; | 35324 | const zir_index = struct_type.zir_index.resolve(ip) orelse return error.AnalysisFail; |
| 35333 | const extended = zir.instructions.items(.data)[@intFromEnum(zir_index)].extended; | 35325 | const extended = zir.instructions.items(.data)[@intFromEnum(zir_index)].extended; |
| 35334 | assert(extended.opcode == .struct_decl); | 35326 | assert(extended.opcode == .struct_decl); |
| ... | @@ -35948,7 +35940,7 @@ fn structFields( | ... | @@ -35948,7 +35940,7 @@ fn structFields( |
| 35948 | const gpa = zcu.gpa; | 35940 | const gpa = zcu.gpa; |
| 35949 | const ip = &zcu.intern_pool; | 35941 | const ip = &zcu.intern_pool; |
| 35950 | const namespace_index = struct_type.namespace; | 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 | const zir_index = struct_type.zir_index.resolve(ip) orelse return error.AnalysisFail; | 35944 | const zir_index = struct_type.zir_index.resolve(ip) orelse return error.AnalysisFail; |
| 35953 | 35945 | ||
| 35954 | const fields_len, _, var extra_index = structZirInfo(zir, zir_index); | 35946 | const fields_len, _, var extra_index = structZirInfo(zir, zir_index); |
| ... | @@ -36149,7 +36141,7 @@ fn structFieldInits( | ... | @@ -36149,7 +36141,7 @@ fn structFieldInits( |
| 36149 | assert(!struct_type.haveFieldInits(ip)); | 36141 | assert(!struct_type.haveFieldInits(ip)); |
| 36150 | 36142 | ||
| 36151 | const namespace_index = struct_type.namespace; | 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 | const zir_index = struct_type.zir_index.resolve(ip) orelse return error.AnalysisFail; | 36145 | const zir_index = struct_type.zir_index.resolve(ip) orelse return error.AnalysisFail; |
| 36154 | const fields_len, _, var extra_index = structZirInfo(zir, zir_index); | 36146 | const fields_len, _, var extra_index = structZirInfo(zir, zir_index); |
| 36155 | 36147 | ||
| ... | @@ -36268,7 +36260,7 @@ fn unionFields( | ... | @@ -36268,7 +36260,7 @@ fn unionFields( |
| 36268 | const zcu = pt.zcu; | 36260 | const zcu = pt.zcu; |
| 36269 | const gpa = zcu.gpa; | 36261 | const gpa = zcu.gpa; |
| 36270 | const ip = &zcu.intern_pool; | 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 | const zir_index = union_type.zir_index.resolve(ip) orelse return error.AnalysisFail; | 36264 | const zir_index = union_type.zir_index.resolve(ip) orelse return error.AnalysisFail; |
| 36273 | const extended = zir.instructions.items(.data)[@intFromEnum(zir_index)].extended; | 36265 | const extended = zir.instructions.items(.data)[@intFromEnum(zir_index)].extended; |
| 36274 | assert(extended.opcode == .union_decl); | 36266 | assert(extended.opcode == .union_decl); |
src/Sema/LowerZon.zig-2| ... | @@ -39,8 +39,6 @@ pub fn run( | ... | @@ -39,8 +39,6 @@ pub fn run( |
| 39 | ) CompileError!InternPool.Index { | 39 | ) CompileError!InternPool.Index { |
| 40 | const pt = sema.pt; | 40 | const pt = sema.pt; |
| 41 | 41 | ||
| 42 | _ = try file.getZoir(pt.zcu); | ||
| 43 | |||
| 44 | const tracked_inst = try pt.zcu.intern_pool.trackZir(pt.zcu.gpa, pt.tid, .{ | 42 | const tracked_inst = try pt.zcu.intern_pool.trackZir(pt.zcu.gpa, pt.tid, .{ |
| 45 | .file = file_index, | 43 | .file = file_index, |
| 46 | .inst = .main_struct_inst, // this is the only trackable instruction in a ZON file | 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,8 +3587,7 @@ pub fn typeDeclSrcLine(ty: Type, zcu: *Zcu) ?u32 { |
| 3587 | }; | 3587 | }; |
| 3588 | const info = tracked.resolveFull(&zcu.intern_pool) orelse return null; | 3588 | const info = tracked.resolveFull(&zcu.intern_pool) orelse return null; |
| 3589 | const file = zcu.fileByIndex(info.file); | 3589 | const file = zcu.fileByIndex(info.file); |
| 3590 | assert(file.zir_loaded); | 3590 | const zir = file.zir.?; |
| 3591 | const zir = file.zir; | ||
| 3592 | const inst = zir.instructions.get(@intFromEnum(info.inst)); | 3591 | const inst = zir.instructions.get(@intFromEnum(info.inst)); |
| 3593 | return switch (inst.tag) { | 3592 | return switch (inst.tag) { |
| 3594 | .struct_init, .struct_init_ref => zir.extraData(Zir.Inst.StructInit, inst.data.pl_node.payload_index).data.abs_line, | 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,7 +3904,7 @@ fn resolveStructInner( |
| 3905 | var comptime_err_ret_trace = std.ArrayList(Zcu.LazySrcLoc).init(gpa); | 3904 | var comptime_err_ret_trace = std.ArrayList(Zcu.LazySrcLoc).init(gpa); |
| 3906 | defer comptime_err_ret_trace.deinit(); | 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 | var sema: Sema = .{ | 3908 | var sema: Sema = .{ |
| 3910 | .pt = pt, | 3909 | .pt = pt, |
| 3911 | .gpa = gpa, | 3910 | .gpa = gpa, |
| ... | @@ -3959,7 +3958,7 @@ fn resolveUnionInner( | ... | @@ -3959,7 +3958,7 @@ fn resolveUnionInner( |
| 3959 | var comptime_err_ret_trace = std.ArrayList(Zcu.LazySrcLoc).init(gpa); | 3958 | var comptime_err_ret_trace = std.ArrayList(Zcu.LazySrcLoc).init(gpa); |
| 3960 | defer comptime_err_ret_trace.deinit(); | 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 | var sema: Sema = .{ | 3962 | var sema: Sema = .{ |
| 3964 | .pt = pt, | 3963 | .pt = pt, |
| 3965 | .gpa = gpa, | 3964 | .gpa = gpa, |
src/Zcu.zig+262-90| ... | @@ -658,24 +658,35 @@ pub const Namespace = struct { | ... | @@ -658,24 +658,35 @@ pub const Namespace = struct { |
| 658 | }; | 658 | }; |
| 659 | 659 | ||
| 660 | pub const File = struct { | 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 | /// Relative to the owning package's root source directory. | 661 | /// Relative to the owning package's root source directory. |
| 667 | /// Memory is stored in gpa, owned by File. | 662 | /// Memory is stored in gpa, owned by File. |
| 668 | sub_file_path: []const u8, | 663 | sub_file_path: []const u8, |
| 669 | /// Whether this is populated depends on `source_loaded`. | 664 | |
| 670 | source: [:0]const u8, | 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 | /// Whether this is populated depends on `status`. | 682 | /// Whether this is populated depends on `status`. |
| 672 | stat: Cache.File.Stat, | 683 | stat: Cache.File.Stat, |
| 673 | /// Whether this is populated or not depends on `tree_loaded`. | 684 | |
| 674 | tree: Ast, | 685 | source: ?[:0]const u8, |
| 675 | /// Whether this is populated or not depends on `zir_loaded`. | 686 | tree: ?Ast, |
| 676 | zir: Zir, | 687 | zir: ?Zir, |
| 677 | /// Cached Zoir, generated lazily. | 688 | zoir: ?Zoir, |
| 678 | zoir: ?Zoir = null, | 689 | |
| 679 | /// Module that this file is a part of, managed externally. | 690 | /// Module that this file is a part of, managed externally. |
| 680 | mod: *Package.Module, | 691 | mod: *Package.Module, |
| 681 | /// Whether this file is a part of multiple packages. This is an error condition which will be reported after AstGen. | 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,19 +694,24 @@ pub const File = struct { |
| 683 | /// List of references to this file, used for multi-package errors. | 694 | /// List of references to this file, used for multi-package errors. |
| 684 | references: std.ArrayListUnmanaged(File.Reference) = .empty, | 695 | references: std.ArrayListUnmanaged(File.Reference) = .empty, |
| 685 | 696 | ||
| 686 | /// The most recent successful ZIR for this file, with no errors. | 697 | /// The ZIR for this file from the last update with no file failures. As such, this ZIR is never |
| 687 | /// This is only populated when a previously successful ZIR | 698 | /// failed (although it may have compile errors). |
| 688 | /// newly introduces compile errors during an update. When ZIR is | 699 | /// |
| 689 | /// successful, this field is unloaded. | 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 | prev_zir: ?*Zir = null, | 706 | prev_zir: ?*Zir = null, |
| 691 | 707 | ||
| 692 | pub const Status = enum { | 708 | /// This field serves a similar purpose to `prev_zir`, but for ZOIR. However, since we do not |
| 693 | never_loaded, | 709 | /// need to map old ZOIR to new ZOIR -- instead only invalidating dependencies if the ZOIR |
| 694 | retryable_failure, | 710 | /// changed -- this field is just a simple boolean. |
| 695 | parse_failure, | 711 | /// |
| 696 | astgen_failure, | 712 | /// When `zoir` is updated, this field is set to `true`. In `updateZirRefs`, if this is `true`, |
| 697 | success_zir, | 713 | /// we invalidate the corresponding `zon_file` dependency, and reset it to `false`. |
| 698 | }; | 714 | zoir_invalidated: bool = false, |
| 699 | 715 | ||
| 700 | /// A single reference to a file. | 716 | /// A single reference to a file. |
| 701 | pub const Reference = union(enum) { | 717 | pub const Reference = union(enum) { |
| ... | @@ -727,23 +743,23 @@ pub const File = struct { | ... | @@ -727,23 +743,23 @@ pub const File = struct { |
| 727 | } | 743 | } |
| 728 | 744 | ||
| 729 | pub fn unloadTree(file: *File, gpa: Allocator) void { | 745 | pub fn unloadTree(file: *File, gpa: Allocator) void { |
| 730 | if (file.tree_loaded) { | 746 | if (file.tree) |*tree| { |
| 731 | file.tree_loaded = false; | 747 | tree.deinit(gpa); |
| 732 | file.tree.deinit(gpa); | 748 | file.tree = null; |
| 733 | } | 749 | } |
| 734 | } | 750 | } |
| 735 | 751 | ||
| 736 | pub fn unloadSource(file: *File, gpa: Allocator) void { | 752 | pub fn unloadSource(file: *File, gpa: Allocator) void { |
| 737 | if (file.source_loaded) { | 753 | if (file.source) |source| { |
| 738 | file.source_loaded = false; | 754 | gpa.free(source); |
| 739 | gpa.free(file.source); | 755 | file.source = null; |
| 740 | } | 756 | } |
| 741 | } | 757 | } |
| 742 | 758 | ||
| 743 | pub fn unloadZir(file: *File, gpa: Allocator) void { | 759 | pub fn unloadZir(file: *File, gpa: Allocator) void { |
| 744 | if (file.zir_loaded) { | 760 | if (file.zir) |*zir| { |
| 745 | file.zir_loaded = false; | 761 | zir.deinit(gpa); |
| 746 | file.zir.deinit(gpa); | 762 | file.zir = null; |
| 747 | } | 763 | } |
| 748 | } | 764 | } |
| 749 | 765 | ||
| ... | @@ -753,8 +769,8 @@ pub const File = struct { | ... | @@ -753,8 +769,8 @@ pub const File = struct { |
| 753 | }; | 769 | }; |
| 754 | 770 | ||
| 755 | pub fn getSource(file: *File, gpa: Allocator) !Source { | 771 | pub fn getSource(file: *File, gpa: Allocator) !Source { |
| 756 | if (file.source_loaded) return Source{ | 772 | if (file.source) |source| return .{ |
| 757 | .bytes = file.source, | 773 | .bytes = source, |
| 758 | .stat = file.stat, | 774 | .stat = file.stat, |
| 759 | }; | 775 | }; |
| 760 | 776 | ||
| ... | @@ -769,18 +785,20 @@ pub const File = struct { | ... | @@ -769,18 +785,20 @@ pub const File = struct { |
| 769 | return error.FileTooBig; | 785 | return error.FileTooBig; |
| 770 | 786 | ||
| 771 | const source = try gpa.allocSentinel(u8, @as(usize, @intCast(stat.size)), 0); | 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 | const amt = try f.readAll(source); | 790 | const amt = try f.readAll(source); |
| 774 | if (amt != stat.size) | 791 | if (amt != stat.size) |
| 775 | return error.UnexpectedEndOfFile; | 792 | return error.UnexpectedEndOfFile; |
| 776 | 793 | ||
| 777 | // Here we do not modify stat fields because this function is the one | 794 | // Here we do not modify stat fields because this function is the one |
| 778 | // used for error reporting. We need to keep the stat fields stale so that | 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 | file.source = source; | 798 | file.source = source; |
| 782 | file.source_loaded = true; | 799 | errdefer comptime unreachable; // don't error after populating `source` |
| 783 | return Source{ | 800 | |
| 801 | return .{ | ||
| 784 | .bytes = source, | 802 | .bytes = source, |
| 785 | .stat = .{ | 803 | .stat = .{ |
| 786 | .size = stat.size, | 804 | .size = stat.size, |
| ... | @@ -791,20 +809,20 @@ pub const File = struct { | ... | @@ -791,20 +809,20 @@ pub const File = struct { |
| 791 | } | 809 | } |
| 792 | 810 | ||
| 793 | pub fn getTree(file: *File, gpa: Allocator) !*const Ast { | 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 | const source = try file.getSource(gpa); | 814 | const source = try file.getSource(gpa); |
| 797 | file.tree = try Ast.parse(gpa, source.bytes, file.getMode()); | 815 | file.tree = try .parse(gpa, source.bytes, file.getMode()); |
| 798 | file.tree_loaded = true; | 816 | return &file.tree.?; |
| 799 | return &file.tree; | ||
| 800 | } | 817 | } |
| 801 | 818 | ||
| 802 | pub fn getZoir(file: *File, zcu: *Zcu) !*const Zoir { | 819 | pub fn getZoir(file: *File, zcu: *Zcu) !*const Zoir { |
| 803 | if (file.zoir) |*zoir| return zoir; | 820 | if (file.zoir) |*zoir| return zoir; |
| 804 | 821 | ||
| 805 | assert(file.tree_loaded); | 822 | const tree = file.tree.?; |
| 806 | assert(file.tree.mode == .zon); | 823 | assert(tree.mode == .zon); |
| 807 | file.zoir = try ZonGen.generate(zcu.gpa, file.tree, .{}); | 824 | |
| 825 | file.zoir = try ZonGen.generate(zcu.gpa, tree, .{}); | ||
| 808 | if (file.zoir.?.hasCompileErrors()) { | 826 | if (file.zoir.?.hasCompileErrors()) { |
| 809 | try zcu.failed_files.putNoClobber(zcu.gpa, file, null); | 827 | try zcu.failed_files.putNoClobber(zcu.gpa, file, null); |
| 810 | return error.AnalysisFail; | 828 | return error.AnalysisFail; |
| ... | @@ -854,13 +872,6 @@ pub const File = struct { | ... | @@ -854,13 +872,6 @@ pub const File = struct { |
| 854 | std.debug.print("{s}:{d}:{d}\n", .{ file.sub_file_path, loc.line + 1, loc.column + 1 }); | 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 | /// Add a reference to this file during AstGen. | 875 | /// Add a reference to this file during AstGen. |
| 865 | pub fn addReference(file: *File, zcu: *Zcu, ref: File.Reference) !void { | 876 | pub fn addReference(file: *File, zcu: *Zcu, ref: File.Reference) !void { |
| 866 | // Don't add the same module root twice. Note that since we always add module roots at the | 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,18 +911,18 @@ pub const File = struct { |
| 900 | 911 | ||
| 901 | // We can only mark children as failed if the ZIR is loaded, which may not | 912 | // We can only mark children as failed if the ZIR is loaded, which may not |
| 902 | // be the case if there were other astgen failures in this file | 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 | if (imports_index == 0) return; | 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 | var extra_index = extra.end; | 920 | var extra_index = extra.end; |
| 910 | for (0..extra.data.imports_len) |_| { | 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 | extra_index = item.end; | 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 | if (mem.eql(u8, import_path, "builtin")) continue; | 926 | if (mem.eql(u8, import_path, "builtin")) continue; |
| 916 | 927 | ||
| 917 | const res = pt.importFile(file, import_path) catch continue; | 928 | const res = pt.importFile(file, import_path) catch continue; |
| ... | @@ -1012,7 +1023,7 @@ pub const SrcLoc = struct { | ... | @@ -1012,7 +1023,7 @@ pub const SrcLoc = struct { |
| 1012 | lazy: LazySrcLoc.Offset, | 1023 | lazy: LazySrcLoc.Offset, |
| 1013 | 1024 | ||
| 1014 | pub fn baseSrcToken(src_loc: SrcLoc) Ast.TokenIndex { | 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 | return tree.firstToken(src_loc.base_node); | 1027 | return tree.firstToken(src_loc.base_node); |
| 1017 | } | 1028 | } |
| 1018 | 1029 | ||
| ... | @@ -1057,7 +1068,6 @@ pub const SrcLoc = struct { | ... | @@ -1057,7 +1068,6 @@ pub const SrcLoc = struct { |
| 1057 | const node_off = traced_off.x; | 1068 | const node_off = traced_off.x; |
| 1058 | const tree = try src_loc.file_scope.getTree(gpa); | 1069 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1059 | const node = src_loc.relativeToNodeIndex(node_off); | 1070 | const node = src_loc.relativeToNodeIndex(node_off); |
| 1060 | assert(src_loc.file_scope.tree_loaded); | ||
| 1061 | return tree.nodeToSpan(node); | 1071 | return tree.nodeToSpan(node); |
| 1062 | }, | 1072 | }, |
| 1063 | .node_offset_main_token => |node_off| { | 1073 | .node_offset_main_token => |node_off| { |
| ... | @@ -1069,7 +1079,6 @@ pub const SrcLoc = struct { | ... | @@ -1069,7 +1079,6 @@ pub const SrcLoc = struct { |
| 1069 | .node_offset_bin_op => |node_off| { | 1079 | .node_offset_bin_op => |node_off| { |
| 1070 | const tree = try src_loc.file_scope.getTree(gpa); | 1080 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1071 | const node = src_loc.relativeToNodeIndex(node_off); | 1081 | const node = src_loc.relativeToNodeIndex(node_off); |
| 1072 | assert(src_loc.file_scope.tree_loaded); | ||
| 1073 | return tree.nodeToSpan(node); | 1082 | return tree.nodeToSpan(node); |
| 1074 | }, | 1083 | }, |
| 1075 | .node_offset_initializer => |node_off| { | 1084 | .node_offset_initializer => |node_off| { |
| ... | @@ -2408,9 +2417,8 @@ pub const LazySrcLoc = struct { | ... | @@ -2408,9 +2417,8 @@ pub const LazySrcLoc = struct { |
| 2408 | if (zir_inst == .main_struct_inst) return .{ file, 0 }; | 2417 | if (zir_inst == .main_struct_inst) return .{ file, 0 }; |
| 2409 | 2418 | ||
| 2410 | // Otherwise, make sure ZIR is loaded. | 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 | const inst = zir.instructions.get(@intFromEnum(zir_inst)); | 2422 | const inst = zir.instructions.get(@intFromEnum(zir_inst)); |
| 2415 | const base_node: Ast.Node.Index = switch (inst.tag) { | 2423 | const base_node: Ast.Node.Index = switch (inst.tag) { |
| 2416 | .declaration => inst.data.declaration.src_node, | 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,6 +2651,189 @@ pub fn loadZirCacheBody(gpa: Allocator, header: Zir.Header, cache_file: std.fs.F |
| 2643 | return zir; | 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 | pub fn markDependeeOutdated( | 2837 | pub fn markDependeeOutdated( |
| 2647 | zcu: *Zcu, | 2838 | zcu: *Zcu, |
| 2648 | /// When we are diffing ZIR and marking things as outdated, we won't yet have marked the dependencies as PO. | 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,19 +3494,6 @@ pub fn optimizeMode(zcu: *const Zcu) std.builtin.OptimizeMode { |
| 3303 | return zcu.root_mod.optimize_mode; | 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 | pub fn handleUpdateExports( | 3497 | pub fn handleUpdateExports( |
| 3320 | zcu: *Zcu, | 3498 | zcu: *Zcu, |
| 3321 | export_indices: []const Export.Index, | 3499 | export_indices: []const Export.Index, |
| ... | @@ -3670,9 +3848,7 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv | ... | @@ -3670,9 +3848,7 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv |
| 3670 | // `test` declarations are analyzed depending on the test filter. | 3848 | // `test` declarations are analyzed depending on the test filter. |
| 3671 | const inst_info = nav.analysis.?.zir_index.resolveFull(ip) orelse continue; | 3849 | const inst_info = nav.analysis.?.zir_index.resolveFull(ip) orelse continue; |
| 3672 | const file = zcu.fileByIndex(inst_info.file); | 3850 | const file = zcu.fileByIndex(inst_info.file); |
| 3673 | // If the file failed AstGen, the TrackedInst refers to the old ZIR. | 3851 | const decl = file.zir.?.getDeclaration(inst_info.inst); |
| 3674 | const zir = if (file.status == .success_zir) file.zir else file.prev_zir.?.*; | ||
| 3675 | const decl = zir.getDeclaration(inst_info.inst); | ||
| 3676 | 3852 | ||
| 3677 | if (!comp.config.is_test or file.mod != zcu.main_mod) continue; | 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,9 +3878,7 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv |
| 3702 | // These are named declarations. They are analyzed only if marked `export`. | 3878 | // These are named declarations. They are analyzed only if marked `export`. |
| 3703 | const inst_info = ip.getNav(nav).analysis.?.zir_index.resolveFull(ip) orelse continue; | 3879 | const inst_info = ip.getNav(nav).analysis.?.zir_index.resolveFull(ip) orelse continue; |
| 3704 | const file = zcu.fileByIndex(inst_info.file); | 3880 | const file = zcu.fileByIndex(inst_info.file); |
| 3705 | // If the file failed AstGen, the TrackedInst refers to the old ZIR. | 3881 | const decl = file.zir.?.getDeclaration(inst_info.inst); |
| 3706 | const zir = if (file.status == .success_zir) file.zir else file.prev_zir.?.*; | ||
| 3707 | const decl = zir.getDeclaration(inst_info.inst); | ||
| 3708 | if (decl.linkage == .@"export") { | 3882 | if (decl.linkage == .@"export") { |
| 3709 | const unit: AnalUnit = .wrap(.{ .nav_val = nav }); | 3883 | const unit: AnalUnit = .wrap(.{ .nav_val = nav }); |
| 3710 | if (!result.contains(unit)) { | 3884 | if (!result.contains(unit)) { |
| ... | @@ -3720,9 +3894,7 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv | ... | @@ -3720,9 +3894,7 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv |
| 3720 | // These are named declarations. They are analyzed only if marked `export`. | 3894 | // These are named declarations. They are analyzed only if marked `export`. |
| 3721 | const inst_info = ip.getNav(nav).analysis.?.zir_index.resolveFull(ip) orelse continue; | 3895 | const inst_info = ip.getNav(nav).analysis.?.zir_index.resolveFull(ip) orelse continue; |
| 3722 | const file = zcu.fileByIndex(inst_info.file); | 3896 | const file = zcu.fileByIndex(inst_info.file); |
| 3723 | // If the file failed AstGen, the TrackedInst refers to the old ZIR. | 3897 | const decl = file.zir.?.getDeclaration(inst_info.inst); |
| 3724 | const zir = if (file.status == .success_zir) file.zir else file.prev_zir.?.*; | ||
| 3725 | const decl = zir.getDeclaration(inst_info.inst); | ||
| 3726 | if (decl.linkage == .@"export") { | 3898 | if (decl.linkage == .@"export") { |
| 3727 | const unit: AnalUnit = .wrap(.{ .nav_val = nav }); | 3899 | const unit: AnalUnit = .wrap(.{ .nav_val = nav }); |
| 3728 | if (!result.contains(unit)) { | 3900 | if (!result.contains(unit)) { |
| ... | @@ -3858,7 +4030,7 @@ pub fn navSrcLine(zcu: *Zcu, nav_index: InternPool.Nav.Index) u32 { | ... | @@ -3858,7 +4030,7 @@ pub fn navSrcLine(zcu: *Zcu, nav_index: InternPool.Nav.Index) u32 { |
| 3858 | const ip = &zcu.intern_pool; | 4030 | const ip = &zcu.intern_pool; |
| 3859 | const inst_info = ip.getNav(nav_index).srcInst(ip).resolveFull(ip).?; | 4031 | const inst_info = ip.getNav(nav_index).srcInst(ip).resolveFull(ip).?; |
| 3860 | const zir = zcu.fileByIndex(inst_info.file).zir; | 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 | pub fn navValue(zcu: *const Zcu, nav_index: InternPool.Nav.Index) Value { | 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,10 +4082,6 @@ fn formatDependee(data: struct { dependee: InternPool.Dependee, zcu: *Zcu }, com |
| 3910 | const zcu = data.zcu; | 4082 | const zcu = data.zcu; |
| 3911 | const ip = &zcu.intern_pool; | 4083 | const ip = &zcu.intern_pool; |
| 3912 | switch (data.dependee) { | 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 | .src_hash => |ti| { | 4085 | .src_hash => |ti| { |
| 3918 | const info = ti.resolveFull(ip) orelse { | 4086 | const info = ti.resolveFull(ip) orelse { |
| 3919 | return writer.writeAll("inst(<lost>)"); | 4087 | return writer.writeAll("inst(<lost>)"); |
| ... | @@ -3934,6 +4102,10 @@ fn formatDependee(data: struct { dependee: InternPool.Dependee, zcu: *Zcu }, com | ... | @@ -3934,6 +4102,10 @@ fn formatDependee(data: struct { dependee: InternPool.Dependee, zcu: *Zcu }, com |
| 3934 | .func => |f| return writer.print("ies('{}')", .{ip.getNav(f.owner_nav).fqn.fmt(ip)}), | 4102 | .func => |f| return writer.print("ies('{}')", .{ip.getNav(f.owner_nav).fqn.fmt(ip)}), |
| 3935 | else => unreachable, | 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 | .embed_file => |ef_idx| { | 4109 | .embed_file => |ef_idx| { |
| 3938 | const ef = ef_idx.get(zcu); | 4110 | const ef = ef_idx.get(zcu); |
| 3939 | return writer.print("embed_file('{s}')", .{std.fs.path.fmtJoin(&.{ | 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,6 +26,8 @@ const Type = @import("../Type.zig"); |
| 26 | const Value = @import("../Value.zig"); | 26 | const Value = @import("../Value.zig"); |
| 27 | const Zcu = @import("../Zcu.zig"); | 27 | const Zcu = @import("../Zcu.zig"); |
| 28 | const Zir = std.zig.Zir; | 28 | const Zir = std.zig.Zir; |
| 29 | const Zoir = std.zig.Zoir; | ||
| 30 | const ZonGen = std.zig.ZonGen; | ||
| 29 | 31 | ||
| 30 | zcu: *Zcu, | 32 | zcu: *Zcu, |
| 31 | 33 | ||
| ... | @@ -73,7 +75,9 @@ pub fn destroyFile(pt: Zcu.PerThread, file_index: Zcu.File.Index) void { | ... | @@ -73,7 +75,9 @@ pub fn destroyFile(pt: Zcu.PerThread, file_index: Zcu.File.Index) void { |
| 73 | if (!is_builtin) gpa.destroy(file); | 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 | pt: Zcu.PerThread, | 81 | pt: Zcu.PerThread, |
| 78 | file: *Zcu.File, | 82 | file: *Zcu.File, |
| 79 | path_digest: Cache.BinDigest, | 83 | path_digest: Cache.BinDigest, |
| ... | @@ -109,7 +113,7 @@ pub fn astGenFile( | ... | @@ -109,7 +113,7 @@ pub fn astGenFile( |
| 109 | 113 | ||
| 110 | break :lock .shared; | 114 | break :lock .shared; |
| 111 | }, | 115 | }, |
| 112 | .parse_failure, .astgen_failure, .success_zir => lock: { | 116 | .astgen_failure, .success => lock: { |
| 113 | const unchanged_metadata = | 117 | const unchanged_metadata = |
| 114 | stat.size == file.stat.size and | 118 | stat.size == file.stat.size and |
| 115 | stat.mtime == file.stat.mtime and | 119 | stat.mtime == file.stat.mtime and |
| ... | @@ -126,6 +130,27 @@ pub fn astGenFile( | ... | @@ -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 | // We ask for a lock in order to coordinate with other zig processes. | 154 | // We ask for a lock in order to coordinate with other zig processes. |
| 130 | // If another process is already working on this file, we will get the cached | 155 | // If another process is already working on this file, we will get the cached |
| 131 | // version. Likewise if we're working on AstGen and another process asks for | 156 | // version. Likewise if we're working on AstGen and another process asks for |
| ... | @@ -180,190 +205,164 @@ pub fn astGenFile( | ... | @@ -180,190 +205,164 @@ pub fn astGenFile( |
| 180 | }; | 205 | }; |
| 181 | defer cache_file.close(); | 206 | defer cache_file.close(); |
| 182 | 207 | ||
| 183 | while (true) { | 208 | const need_update = while (true) { |
| 184 | update: { | 209 | const result = switch (file.getMode()) { |
| 185 | // First we read the header to determine the lengths of arrays. | 210 | inline else => |mode| try loadZirZoirCache(zcu, cache_file, stat, file, mode), |
| 186 | const header = cache_file.reader().readStruct(Zir.Header) catch |err| switch (err) { | 211 | }; |
| 187 | // This can happen if Zig bails out of this function between creating | 212 | switch (result) { |
| 188 | // the cached file and writing it. | 213 | .success => { |
| 189 | error.EndOfStream => break :update, | 214 | log.debug("AstGen cached success: {s}", .{file.sub_file_path}); |
| 190 | else => |e| return e, | 215 | break false; |
| 191 | }; | 216 | }, |
| 192 | const unchanged_metadata = | 217 | .invalid => {}, |
| 193 | stat.size == header.stat_size and | 218 | .truncated => log.warn("unexpected EOF reading cached ZIR for {s}", .{file.sub_file_path}), |
| 194 | stat.mtime == header.stat_mtime and | 219 | .stale => log.debug("AstGen cache stale: {s}", .{file.sub_file_path}), |
| 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; | ||
| 232 | } | 220 | } |
| 233 | 221 | ||
| 234 | // If we already have the exclusive lock then it is our job to update. | 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 | // Otherwise, unlock to give someone a chance to get the exclusive lock | 224 | // Otherwise, unlock to give someone a chance to get the exclusive lock |
| 237 | // and then upgrade to an exclusive lock. | 225 | // and then upgrade to an exclusive lock. |
| 238 | cache_file.unlock(); | 226 | cache_file.unlock(); |
| 239 | lock = .exclusive; | 227 | lock = .exclusive; |
| 240 | try cache_file.lock(lock); | 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. | 231 | if (need_update) { |
| 244 | cache_file.setEndPos(0) catch |err| switch (err) { | 232 | // The cache is definitely stale so delete the contents to avoid an underwrite later. |
| 245 | error.FileTooBig => unreachable, // 0 is not too big | 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, | 238 | if (stat.size > std.math.maxInt(u32)) |
| 248 | }; | 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: | 247 | file.source = source; |
| 253 | // | 248 | |
| 254 | // 1. In case an update to the file causes a Parse or AstGen failure, we | 249 | // Any potential AST errors are converted to ZIR errors when we run AstGen/ZonGen. |
| 255 | // need to compare two successful ZIR files in order to proceed with an | 250 | file.tree = try Ast.parse(gpa, source, file.getMode()); |
| 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); | ||
| 273 | 251 | ||
| 274 | if (stat.size > std.math.maxInt(u32)) | 252 | switch (file.getMode()) { |
| 275 | return error.FileTooBig; | 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); | 272 | log.debug("AstGen fresh success: {s}", .{file.sub_file_path}); |
| 278 | defer if (!file.source_loaded) gpa.free(source); | 273 | } |
| 279 | const amt = try source_file.readAll(source); | ||
| 280 | if (amt != stat.size) | ||
| 281 | return error.UnexpectedEndOfFile; | ||
| 282 | 274 | ||
| 283 | file.stat = .{ | 275 | file.stat = .{ |
| 284 | .size = stat.size, | 276 | .size = stat.size, |
| 285 | .inode = stat.inode, | 277 | .inode = stat.inode, |
| 286 | .mtime = stat.mtime, | 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); | 281 | // Now, `zir` or `zoir` is definitely populated and up-to-date. |
| 292 | file.tree_loaded = true; | 282 | // Mark file successes/failures as needed. |
| 293 | 283 | ||
| 294 | // Any potential AST errors are converted to ZIR errors here. | 284 | switch (file.getMode()) { |
| 295 | file.zir = try AstGen.generate(gpa, file.tree); | 285 | .zig => { |
| 296 | file.zir_loaded = true; | 286 | if (file.zir.?.hasCompileErrors()) { |
| 297 | file.prev_status = file.status; | 287 | comp.mutex.lock(); |
| 298 | file.status = .success_zir; | 288 | defer comp.mutex.unlock(); |
| 299 | log.debug("AstGen fresh success: {s}", .{file.sub_file_path}); | 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) | 309 | switch (file.status) { |
| 302 | try gpa.alloc([8]u8, file.zir.instructions.len) | 310 | .never_loaded => unreachable, |
| 303 | else | 311 | .retryable_failure => unreachable, |
| 304 | undefined; | 312 | .astgen_failure => return error.AnalysisFail, |
| 305 | defer if (Zcu.data_has_safety_tag) gpa.free(safety_buffer); | 313 | .success => return, |
| 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 | } | ||
| 319 | } | 314 | } |
| 315 | } | ||
| 320 | 316 | ||
| 321 | const header: Zir.Header = .{ | 317 | fn loadZirZoirCache( |
| 322 | .instructions_len = @as(u32, @intCast(file.zir.instructions.len)), | 318 | zcu: *Zcu, |
| 323 | .string_bytes_len = @as(u32, @intCast(file.zir.string_bytes.len)), | 319 | cache_file: std.fs.File, |
| 324 | .extra_len = @as(u32, @intCast(file.zir.extra.len)), | 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, | 326 | const gpa = zcu.gpa; |
| 327 | .stat_inode = stat.inode, | 327 | |
| 328 | .stat_mtime = stat.mtime, | 328 | const Header = switch (mode) { |
| 329 | }; | 329 | .zig => Zir.Header, |
| 330 | var iovecs = [_]std.posix.iovec_const{ | 330 | .zon => Zoir.Header, |
| 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 | }, | ||
| 351 | }; | 331 | }; |
| 352 | cache_file.writevAll(&iovecs) catch |err| { | 332 | |
| 353 | log.warn("unable to write cached ZIR code for {}{s} to {}{s}: {s}", .{ | 333 | // First we read the header to determine the lengths of arrays. |
| 354 | file.mod.root, file.sub_file_path, cache_directory, &hex_digest, @errorName(err), | 334 | const header = cache_file.reader().readStruct(Header) catch |err| switch (err) { |
| 355 | }); | 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()) { | 341 | const unchanged_metadata = |
| 359 | comp.mutex.lock(); | 342 | stat.size == header.stat_size and |
| 360 | defer comp.mutex.unlock(); | 343 | stat.mtime == header.stat_mtime and |
| 361 | try zcu.failed_files.putNoClobber(gpa, file, null); | 344 | stat.inode == header.stat_inode; |
| 345 | |||
| 346 | if (!unchanged_metadata) { | ||
| 347 | return .stale; | ||
| 362 | } | 348 | } |
| 363 | if (file.zir.loweringFailed()) { | 349 | |
| 364 | file.status = .astgen_failure; | 350 | switch (mode) { |
| 365 | return error.AnalysisFail; | 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 | const UpdatedFile = struct { | 368 | const UpdatedFile = struct { |
| ... | @@ -384,24 +383,32 @@ pub fn updateZirRefs(pt: Zcu.PerThread) Allocator.Error!void { | ... | @@ -384,24 +383,32 @@ pub fn updateZirRefs(pt: Zcu.PerThread) Allocator.Error!void { |
| 384 | const gpa = zcu.gpa; | 383 | const gpa = zcu.gpa; |
| 385 | 384 | ||
| 386 | // We need to visit every updated File for every TrackedInst in InternPool. | 385 | // We need to visit every updated File for every TrackedInst in InternPool. |
| 386 | // This only includes Zig files; ZON files are omitted. | ||
| 387 | var updated_files: std.AutoArrayHashMapUnmanaged(Zcu.File.Index, UpdatedFile) = .empty; | 387 | var updated_files: std.AutoArrayHashMapUnmanaged(Zcu.File.Index, UpdatedFile) = .empty; |
| 388 | defer cleanupUpdatedFiles(gpa, &updated_files); | 388 | defer cleanupUpdatedFiles(gpa, &updated_files); |
| 389 | |||
| 389 | for (zcu.import_table.values()) |file_index| { | 390 | for (zcu.import_table.values()) |file_index| { |
| 390 | const file = zcu.fileByIndex(file_index); | 391 | const file = zcu.fileByIndex(file_index); |
| 391 | if (file.prev_status != file.status and file.prev_status != .never_loaded) { | 392 | assert(file.status == .success); |
| 392 | try zcu.markDependeeOutdated(.not_marked_po, .{ .file = file_index }); | 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 | const old_zir = file.prev_zir orelse continue; | 403 | const old_zir = file.prev_zir orelse continue; |
| 395 | const new_zir = file.zir; | 404 | const new_zir = file.zir.?; |
| 396 | const gop = try updated_files.getOrPut(gpa, file_index); | 405 | const gop = try updated_files.getOrPut(gpa, file_index); |
| 397 | assert(!gop.found_existing); | 406 | assert(!gop.found_existing); |
| 398 | gop.value_ptr.* = .{ | 407 | gop.value_ptr.* = .{ |
| 399 | .file = file, | 408 | .file = file, |
| 400 | .inst_map = .{}, | 409 | .inst_map = .{}, |
| 401 | }; | 410 | }; |
| 402 | if (!new_zir.loweringFailed()) { | 411 | try Zcu.mapOldZirToNew(gpa, old_zir.*, new_zir, &gop.value_ptr.inst_map); |
| 403 | try Zcu.mapOldZirToNew(gpa, old_zir.*, file.zir, &gop.value_ptr.inst_map); | ||
| 404 | } | ||
| 405 | } | 412 | } |
| 406 | 413 | ||
| 407 | if (updated_files.count() == 0) | 414 | if (updated_files.count() == 0) |
| ... | @@ -421,13 +428,9 @@ pub fn updateZirRefs(pt: Zcu.PerThread) Allocator.Error!void { | ... | @@ -421,13 +428,9 @@ pub fn updateZirRefs(pt: Zcu.PerThread) Allocator.Error!void { |
| 421 | .index = @intCast(tracked_inst_unwrapped_index), | 428 | .index = @intCast(tracked_inst_unwrapped_index), |
| 422 | }).wrap(ip); | 429 | }).wrap(ip); |
| 423 | const new_inst = updated_file.inst_map.get(old_inst) orelse { | 430 | const new_inst = updated_file.inst_map.get(old_inst) orelse { |
| 424 | // Tracking failed for this instruction. | 431 | // Tracking failed for this instruction due to changes in the ZIR. |
| 425 | // This may be due to changes in the ZIR, or AstGen might have failed due to a very broken file. | 432 | // Invalidate associated `src_hash` deps. |
| 426 | // Either way, invalidate associated `src_hash` deps. | 433 | log.debug("tracking failed for %{d}", .{old_inst}); |
| 427 | log.debug("tracking failed for %{d}{s}", .{ | ||
| 428 | old_inst, | ||
| 429 | if (file.zir.loweringFailed()) " due to AstGen failure" else "", | ||
| 430 | }); | ||
| 431 | tracked_inst.inst = .lost; | 434 | tracked_inst.inst = .lost; |
| 432 | try zcu.markDependeeOutdated(.not_marked_po, .{ .src_hash = tracked_inst_index }); | 435 | try zcu.markDependeeOutdated(.not_marked_po, .{ .src_hash = tracked_inst_index }); |
| 433 | continue; | 436 | continue; |
| ... | @@ -435,7 +438,7 @@ pub fn updateZirRefs(pt: Zcu.PerThread) Allocator.Error!void { | ... | @@ -435,7 +438,7 @@ pub fn updateZirRefs(pt: Zcu.PerThread) Allocator.Error!void { |
| 435 | tracked_inst.inst = InternPool.TrackedInst.MaybeLost.ZirIndex.wrap(new_inst); | 438 | tracked_inst.inst = InternPool.TrackedInst.MaybeLost.ZirIndex.wrap(new_inst); |
| 436 | 439 | ||
| 437 | const old_zir = file.prev_zir.?.*; | 440 | const old_zir = file.prev_zir.?.*; |
| 438 | const new_zir = file.zir; | 441 | const new_zir = file.zir.?; |
| 439 | const old_tag = old_zir.instructions.items(.tag)[@intFromEnum(old_inst)]; | 442 | const old_tag = old_zir.instructions.items(.tag)[@intFromEnum(old_inst)]; |
| 440 | const old_data = old_zir.instructions.items(.data)[@intFromEnum(old_inst)]; | 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,23 +535,19 @@ pub fn updateZirRefs(pt: Zcu.PerThread) Allocator.Error!void { |
| 532 | 535 | ||
| 533 | for (updated_files.keys(), updated_files.values()) |file_index, updated_file| { | 536 | for (updated_files.keys(), updated_files.values()) |file_index, updated_file| { |
| 534 | const file = updated_file.file; | 537 | const file = updated_file.file; |
| 535 | if (file.zir.loweringFailed()) { | 538 | |
| 536 | // Keep `prev_zir` around: it's the last usable ZIR. | 539 | const prev_zir = file.prev_zir.?; |
| 537 | // Don't update the namespace, as we have no new data to update *to*. | 540 | file.prev_zir = null; |
| 538 | } else { | 541 | prev_zir.deinit(gpa); |
| 539 | const prev_zir = file.prev_zir.?; | 542 | gpa.destroy(prev_zir); |
| 540 | file.prev_zir = null; | 543 | |
| 541 | prev_zir.deinit(gpa); | 544 | // For every file which has changed, re-scan the namespace of the file's root struct type. |
| 542 | gpa.destroy(prev_zir); | 545 | // These types are special-cased because they don't have an enclosing declaration which will |
| 543 | 546 | // be re-analyzed (causing the struct's namespace to be re-scanned). It's fine to do this | |
| 544 | // For every file which has changed, re-scan the namespace of the file's root struct type. | 547 | // now because this work is fast (no actual Sema work is happening, we're just updating the |
| 545 | // These types are special-cased because they don't have an enclosing declaration which will | 548 | // namespace contents). We must do this after updating ZIR refs above, since `scanNamespace` |
| 546 | // be re-analyzed (causing the struct's namespace to be re-scanned). It's fine to do this | 549 | // will track some instructions. |
| 547 | // now because this work is fast (no actual Sema work is happening, we're just updating the | 550 | try pt.updateFileNamespace(file_index); |
| 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 | } | ||
| 552 | } | 551 | } |
| 553 | } | 552 | } |
| 554 | 553 | ||
| ... | @@ -750,6 +749,7 @@ pub fn ensureComptimeUnitUpToDate(pt: Zcu.PerThread, cu_id: InternPool.ComptimeU | ... | @@ -750,6 +749,7 @@ pub fn ensureComptimeUnitUpToDate(pt: Zcu.PerThread, cu_id: InternPool.ComptimeU |
| 750 | kv.value.destroy(gpa); | 749 | kv.value.destroy(gpa); |
| 751 | } | 750 | } |
| 752 | _ = zcu.transitive_failed_analysis.swapRemove(anal_unit); | 751 | _ = zcu.transitive_failed_analysis.swapRemove(anal_unit); |
| 752 | zcu.intern_pool.removeDependenciesForDepender(gpa, anal_unit); | ||
| 753 | } | 753 | } |
| 754 | } else { | 754 | } else { |
| 755 | // We can trust the current information about this unit. | 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,14 +801,7 @@ fn analyzeComptimeUnit(pt: Zcu.PerThread, cu_id: InternPool.ComptimeUnit.Id) Zcu |
| 801 | 801 | ||
| 802 | const inst_resolved = comptime_unit.zir_index.resolveFull(ip) orelse return error.AnalysisFail; | 802 | const inst_resolved = comptime_unit.zir_index.resolveFull(ip) orelse return error.AnalysisFail; |
| 803 | const file = zcu.fileByIndex(inst_resolved.file); | 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 | 804 | const zir = file.zir.?; |
| 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); | ||
| 812 | 805 | ||
| 813 | try zcu.analysis_in_progress.put(gpa, anal_unit, {}); | 806 | try zcu.analysis_in_progress.put(gpa, anal_unit, {}); |
| 814 | defer assert(zcu.analysis_in_progress.swapRemove(anal_unit)); | 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,6 +921,7 @@ pub fn ensureNavValUpToDate(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu |
| 928 | kv.value.destroy(gpa); | 921 | kv.value.destroy(gpa); |
| 929 | } | 922 | } |
| 930 | _ = zcu.transitive_failed_analysis.swapRemove(anal_unit); | 923 | _ = zcu.transitive_failed_analysis.swapRemove(anal_unit); |
| 924 | ip.removeDependenciesForDepender(gpa, anal_unit); | ||
| 931 | } else { | 925 | } else { |
| 932 | // We can trust the current information about this unit. | 926 | // We can trust the current information about this unit. |
| 933 | if (prev_failed) return error.AnalysisFail; | 927 | if (prev_failed) return error.AnalysisFail; |
| ... | @@ -998,14 +992,7 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr | ... | @@ -998,14 +992,7 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr |
| 998 | 992 | ||
| 999 | const inst_resolved = old_nav.analysis.?.zir_index.resolveFull(ip) orelse return error.AnalysisFail; | 993 | const inst_resolved = old_nav.analysis.?.zir_index.resolveFull(ip) orelse return error.AnalysisFail; |
| 1000 | const file = zcu.fileByIndex(inst_resolved.file); | 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 | 995 | const zir = file.zir.?; |
| 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); | ||
| 1009 | 996 | ||
| 1010 | try zcu.analysis_in_progress.put(gpa, anal_unit, {}); | 997 | try zcu.analysis_in_progress.put(gpa, anal_unit, {}); |
| 1011 | errdefer _ = zcu.analysis_in_progress.swapRemove(anal_unit); | 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,6 +1293,7 @@ pub fn ensureNavTypeUpToDate(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zc |
| 1306 | kv.value.destroy(gpa); | 1293 | kv.value.destroy(gpa); |
| 1307 | } | 1294 | } |
| 1308 | _ = zcu.transitive_failed_analysis.swapRemove(anal_unit); | 1295 | _ = zcu.transitive_failed_analysis.swapRemove(anal_unit); |
| 1296 | ip.removeDependenciesForDepender(gpa, anal_unit); | ||
| 1309 | } else { | 1297 | } else { |
| 1310 | // We can trust the current information about this unit. | 1298 | // We can trust the current information about this unit. |
| 1311 | if (prev_failed) return error.AnalysisFail; | 1299 | if (prev_failed) return error.AnalysisFail; |
| ... | @@ -1376,14 +1364,7 @@ fn analyzeNavType(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileEr | ... | @@ -1376,14 +1364,7 @@ fn analyzeNavType(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileEr |
| 1376 | 1364 | ||
| 1377 | const inst_resolved = old_nav.analysis.?.zir_index.resolveFull(ip) orelse return error.AnalysisFail; | 1365 | const inst_resolved = old_nav.analysis.?.zir_index.resolveFull(ip) orelse return error.AnalysisFail; |
| 1378 | const file = zcu.fileByIndex(inst_resolved.file); | 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 | 1367 | const zir = file.zir.?; |
| 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); | ||
| 1387 | 1368 | ||
| 1388 | try zcu.analysis_in_progress.put(gpa, anal_unit, {}); | 1369 | try zcu.analysis_in_progress.put(gpa, anal_unit, {}); |
| 1389 | defer _ = zcu.analysis_in_progress.swapRemove(anal_unit); | 1370 | defer _ = zcu.analysis_in_progress.swapRemove(anal_unit); |
| ... | @@ -1758,7 +1739,7 @@ fn createFileRootStruct( | ... | @@ -1758,7 +1739,7 @@ fn createFileRootStruct( |
| 1758 | const gpa = zcu.gpa; | 1739 | const gpa = zcu.gpa; |
| 1759 | const ip = &zcu.intern_pool; | 1740 | const ip = &zcu.intern_pool; |
| 1760 | const file = zcu.fileByIndex(file_index); | 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 | assert(extended.opcode == .struct_decl); | 1743 | assert(extended.opcode == .struct_decl); |
| 1763 | const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small); | 1744 | const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small); |
| 1764 | assert(!small.has_captures_len); | 1745 | assert(!small.has_captures_len); |
| ... | @@ -1766,16 +1747,16 @@ fn createFileRootStruct( | ... | @@ -1766,16 +1747,16 @@ fn createFileRootStruct( |
| 1766 | assert(small.layout == .auto); | 1747 | assert(small.layout == .auto); |
| 1767 | var extra_index: usize = extended.operand + @typeInfo(Zir.Inst.StructDecl).@"struct".fields.len; | 1748 | var extra_index: usize = extended.operand + @typeInfo(Zir.Inst.StructDecl).@"struct".fields.len; |
| 1768 | const fields_len = if (small.has_fields_len) blk: { | 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 | extra_index += 1; | 1751 | extra_index += 1; |
| 1771 | break :blk fields_len; | 1752 | break :blk fields_len; |
| 1772 | } else 0; | 1753 | } else 0; |
| 1773 | const decls_len = if (small.has_decls_len) blk: { | 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 | extra_index += 1; | 1756 | extra_index += 1; |
| 1776 | break :blk decls_len; | 1757 | break :blk decls_len; |
| 1777 | } else 0; | 1758 | } else 0; |
| 1778 | const decls = file.zir.bodySlice(extra_index, decls_len); | 1759 | const decls = file.zir.?.bodySlice(extra_index, decls_len); |
| 1779 | extra_index += decls_len; | 1760 | extra_index += decls_len; |
| 1780 | 1761 | ||
| 1781 | const tracked_inst = try ip.trackZir(gpa, pt.tid, .{ | 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,7 +1814,6 @@ fn updateFileNamespace(pt: Zcu.PerThread, file_index: Zcu.File.Index) Allocator. |
| 1833 | const zcu = pt.zcu; | 1814 | const zcu = pt.zcu; |
| 1834 | 1815 | ||
| 1835 | const file = zcu.fileByIndex(file_index); | 1816 | const file = zcu.fileByIndex(file_index); |
| 1836 | assert(file.status == .success_zir); | ||
| 1837 | const file_root_type = zcu.fileRootType(file_index); | 1817 | const file_root_type = zcu.fileRootType(file_index); |
| 1838 | if (file_root_type == .none) return; | 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,17 +1824,17 @@ fn updateFileNamespace(pt: Zcu.PerThread, file_index: Zcu.File.Index) Allocator. |
| 1844 | 1824 | ||
| 1845 | const namespace_index = Type.fromInterned(file_root_type).getNamespaceIndex(zcu); | 1825 | const namespace_index = Type.fromInterned(file_root_type).getNamespaceIndex(zcu); |
| 1846 | const decls = decls: { | 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 | const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small); | 1828 | const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small); |
| 1849 | 1829 | ||
| 1850 | var extra_index: usize = extended.operand + @typeInfo(Zir.Inst.StructDecl).@"struct".fields.len; | 1830 | var extra_index: usize = extended.operand + @typeInfo(Zir.Inst.StructDecl).@"struct".fields.len; |
| 1851 | extra_index += @intFromBool(small.has_fields_len); | 1831 | extra_index += @intFromBool(small.has_fields_len); |
| 1852 | const decls_len = if (small.has_decls_len) blk: { | 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 | extra_index += 1; | 1834 | extra_index += 1; |
| 1855 | break :blk decls_len; | 1835 | break :blk decls_len; |
| 1856 | } else 0; | 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 | try pt.scanNamespace(namespace_index, decls); | 1839 | try pt.scanNamespace(namespace_index, decls); |
| 1860 | zcu.namespacePtr(namespace_index).generation = zcu.generation; | 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,15 +1845,11 @@ fn semaFile(pt: Zcu.PerThread, file_index: Zcu.File.Index) Zcu.SemaError!void { |
| 1865 | defer tracy.end(); | 1845 | defer tracy.end(); |
| 1866 | 1846 | ||
| 1867 | const zcu = pt.zcu; | 1847 | const zcu = pt.zcu; |
| 1868 | const gpa = zcu.gpa; | ||
| 1869 | const file = zcu.fileByIndex(file_index); | 1848 | const file = zcu.fileByIndex(file_index); |
| 1870 | assert(file.getMode() == .zig); | 1849 | assert(file.getMode() == .zig); |
| 1871 | assert(zcu.fileRootType(file_index) == .none); | 1850 | assert(zcu.fileRootType(file_index) == .none); |
| 1872 | 1851 | ||
| 1873 | if (file.status != .success_zir) { | 1852 | assert(file.zir != null); |
| 1874 | return error.AnalysisFail; | ||
| 1875 | } | ||
| 1876 | assert(file.zir_loaded); | ||
| 1877 | 1853 | ||
| 1878 | const new_namespace_index = try pt.createNamespace(.{ | 1854 | const new_namespace_index = try pt.createNamespace(.{ |
| 1879 | .parent = .none, | 1855 | .parent = .none, |
| ... | @@ -1883,39 +1859,9 @@ fn semaFile(pt: Zcu.PerThread, file_index: Zcu.File.Index) Zcu.SemaError!void { | ... | @@ -1883,39 +1859,9 @@ fn semaFile(pt: Zcu.PerThread, file_index: Zcu.File.Index) Zcu.SemaError!void { |
| 1883 | }); | 1859 | }); |
| 1884 | const struct_ty = try pt.createFileRootStruct(file_index, new_namespace_index, false); | 1860 | const struct_ty = try pt.createFileRootStruct(file_index, new_namespace_index, false); |
| 1885 | errdefer zcu.intern_pool.remove(pt.tid, struct_ty); | 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 | const zcu = pt.zcu; | 1865 | const zcu = pt.zcu; |
| 1920 | const gpa = zcu.gpa; | 1866 | const gpa = zcu.gpa; |
| 1921 | 1867 | ||
| ... | @@ -1983,15 +1929,12 @@ pub fn importPkg(pt: Zcu.PerThread, mod: *Module) !Zcu.ImportFileResult { | ... | @@ -1983,15 +1929,12 @@ pub fn importPkg(pt: Zcu.PerThread, mod: *Module) !Zcu.ImportFileResult { |
| 1983 | gop.value_ptr.* = new_file_index; | 1929 | gop.value_ptr.* = new_file_index; |
| 1984 | new_file.* = .{ | 1930 | new_file.* = .{ |
| 1985 | .sub_file_path = sub_file_path, | 1931 | .sub_file_path = sub_file_path, |
| 1986 | .source = undefined, | ||
| 1987 | .source_loaded = false, | ||
| 1988 | .tree_loaded = false, | ||
| 1989 | .zir_loaded = false, | ||
| 1990 | .stat = undefined, | 1932 | .stat = undefined, |
| 1991 | .tree = undefined, | 1933 | .source = null, |
| 1992 | .zir = undefined, | 1934 | .tree = null, |
| 1935 | .zir = null, | ||
| 1936 | .zoir = null, | ||
| 1993 | .status = .never_loaded, | 1937 | .status = .never_loaded, |
| 1994 | .prev_status = .never_loaded, | ||
| 1995 | .mod = mod, | 1938 | .mod = mod, |
| 1996 | }; | 1939 | }; |
| 1997 | 1940 | ||
| ... | @@ -2004,13 +1947,19 @@ pub fn importPkg(pt: Zcu.PerThread, mod: *Module) !Zcu.ImportFileResult { | ... | @@ -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 | /// Also called from Sema during semantic analysis. | 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 | pub fn importFile( | 1953 | pub fn importFile( |
| 2010 | pt: Zcu.PerThread, | 1954 | pt: Zcu.PerThread, |
| 2011 | cur_file: *Zcu.File, | 1955 | cur_file: *Zcu.File, |
| 2012 | import_string: []const u8, | 1956 | import_string: []const u8, |
| 2013 | ) !Zcu.ImportFileResult { | 1957 | ) error{ |
| 1958 | OutOfMemory, | ||
| 1959 | ModuleNotFound, | ||
| 1960 | ImportOutsideModulePath, | ||
| 1961 | CurrentWorkingDirectoryUnlinked, | ||
| 1962 | }!Zcu.ImportFileResult { | ||
| 2014 | const zcu = pt.zcu; | 1963 | const zcu = pt.zcu; |
| 2015 | const mod = cur_file.mod; | 1964 | const mod = cur_file.mod; |
| 2016 | 1965 | ||
| ... | @@ -2068,7 +2017,10 @@ pub fn importFile( | ... | @@ -2068,7 +2017,10 @@ pub fn importFile( |
| 2068 | defer gpa.free(resolved_root_path); | 2017 | defer gpa.free(resolved_root_path); |
| 2069 | 2018 | ||
| 2070 | const sub_file_path = p: { | 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 | errdefer gpa.free(relative); | 2024 | errdefer gpa.free(relative); |
| 2073 | 2025 | ||
| 2074 | if (!isUpDir(relative) and !std.fs.path.isAbsolute(relative)) { | 2026 | if (!isUpDir(relative) and !std.fs.path.isAbsolute(relative)) { |
| ... | @@ -2096,15 +2048,15 @@ pub fn importFile( | ... | @@ -2096,15 +2048,15 @@ pub fn importFile( |
| 2096 | gop.value_ptr.* = new_file_index; | 2048 | gop.value_ptr.* = new_file_index; |
| 2097 | new_file.* = .{ | 2049 | new_file.* = .{ |
| 2098 | .sub_file_path = sub_file_path, | 2050 | .sub_file_path = sub_file_path, |
| 2099 | .source = undefined, | 2051 | |
| 2100 | .source_loaded = false, | ||
| 2101 | .tree_loaded = false, | ||
| 2102 | .zir_loaded = false, | ||
| 2103 | .stat = undefined, | ||
| 2104 | .tree = undefined, | ||
| 2105 | .zir = undefined, | ||
| 2106 | .status = .never_loaded, | 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 | .mod = mod, | 2060 | .mod = mod, |
| 2109 | }; | 2061 | }; |
| 2110 | 2062 | ||
| ... | @@ -2441,7 +2393,7 @@ const ScanDeclIter = struct { | ... | @@ -2441,7 +2393,7 @@ const ScanDeclIter = struct { |
| 2441 | const namespace = zcu.namespacePtr(namespace_index); | 2393 | const namespace = zcu.namespacePtr(namespace_index); |
| 2442 | const gpa = zcu.gpa; | 2394 | const gpa = zcu.gpa; |
| 2443 | const file = namespace.fileScope(zcu); | 2395 | const file = namespace.fileScope(zcu); |
| 2444 | const zir = file.zir; | 2396 | const zir = file.zir.?; |
| 2445 | const ip = &zcu.intern_pool; | 2397 | const ip = &zcu.intern_pool; |
| 2446 | 2398 | ||
| 2447 | const decl = zir.getDeclaration(decl_inst); | 2399 | const decl = zir.getDeclaration(decl_inst); |
| ... | @@ -2591,7 +2543,7 @@ fn analyzeFnBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaE | ... | @@ -2591,7 +2543,7 @@ fn analyzeFnBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaE |
| 2591 | const func = zcu.funcInfo(func_index); | 2543 | const func = zcu.funcInfo(func_index); |
| 2592 | const inst_info = func.zir_body_inst.resolveFull(ip) orelse return error.AnalysisFail; | 2544 | const inst_info = func.zir_body_inst.resolveFull(ip) orelse return error.AnalysisFail; |
| 2593 | const file = zcu.fileByIndex(inst_info.file); | 2545 | const file = zcu.fileByIndex(inst_info.file); |
| 2594 | const zir = file.zir; | 2546 | const zir = file.zir.?; |
| 2595 | 2547 | ||
| 2596 | try zcu.analysis_in_progress.put(gpa, anal_unit, {}); | 2548 | try zcu.analysis_in_progress.put(gpa, anal_unit, {}); |
| 2597 | errdefer _ = zcu.analysis_in_progress.swapRemove(anal_unit); | 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,11 +2795,32 @@ pub fn getErrorValueFromSlice(pt: Zcu.PerThread, name: []const u8) Allocator.Err |
| 2843 | /// Removes any entry from `Zcu.failed_files` associated with `file`. Acquires `Compilation.mutex` as needed. | 2795 | /// Removes any entry from `Zcu.failed_files` associated with `file`. Acquires `Compilation.mutex` as needed. |
| 2844 | /// `file.zir` must be unchanged from the last update, as it is used to determine if there is such an entry. | 2796 | /// `file.zir` must be unchanged from the last update, as it is used to determine if there is such an entry. |
| 2845 | fn lockAndClearFileCompileError(pt: Zcu.PerThread, file: *Zcu.File) void { | 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 | pt.zcu.comp.mutex.lock(); | 2819 | pt.zcu.comp.mutex.lock(); |
| 2848 | defer pt.zcu.comp.mutex.unlock(); | 2820 | defer pt.zcu.comp.mutex.unlock(); |
| 2849 | if (pt.zcu.failed_files.fetchSwapRemove(file)) |kv| { | 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,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 | pub fn reportRetryableAstGenError( | 3180 | pub fn reportRetryableAstGenError( |
| 3207 | pt: Zcu.PerThread, | 3181 | pt: Zcu.PerThread, |
| 3208 | src: Zcu.AstGenSrc, | 3182 | src: Zcu.AstGenSrc, |
| ... | @@ -3238,13 +3212,18 @@ pub fn reportRetryableAstGenError( | ... | @@ -3238,13 +3212,18 @@ pub fn reportRetryableAstGenError( |
| 3238 | }); | 3212 | }); |
| 3239 | errdefer err_msg.destroy(gpa); | 3213 | errdefer err_msg.destroy(gpa); |
| 3240 | 3214 | ||
| 3241 | { | 3215 | zcu.comp.mutex.lock(); |
| 3242 | zcu.comp.mutex.lock(); | 3216 | defer zcu.comp.mutex.unlock(); |
| 3243 | defer zcu.comp.mutex.unlock(); | 3217 | const gop = try zcu.failed_files.getOrPut(gpa, file); |
| 3244 | try zcu.failed_files.putNoClobber(gpa, file, err_msg); | 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 | pub fn reportRetryableFileError( | 3227 | pub fn reportRetryableFileError( |
| 3249 | pt: Zcu.PerThread, | 3228 | pt: Zcu.PerThread, |
| 3250 | file_index: Zcu.File.Index, | 3229 | file_index: Zcu.File.Index, |
| ... | @@ -3778,8 +3757,7 @@ fn recreateStructType( | ... | @@ -3778,8 +3757,7 @@ fn recreateStructType( |
| 3778 | 3757 | ||
| 3779 | const inst_info = key.zir_index.resolveFull(ip).?; | 3758 | const inst_info = key.zir_index.resolveFull(ip).?; |
| 3780 | const file = zcu.fileByIndex(inst_info.file); | 3759 | const file = zcu.fileByIndex(inst_info.file); |
| 3781 | assert(file.status == .success_zir); // otherwise inst tracking failed | 3760 | const zir = file.zir.?; |
| 3782 | const zir = file.zir; | ||
| 3783 | 3761 | ||
| 3784 | assert(zir.instructions.items(.tag)[@intFromEnum(inst_info.inst)] == .extended); | 3762 | assert(zir.instructions.items(.tag)[@intFromEnum(inst_info.inst)] == .extended); |
| 3785 | const extended = zir.instructions.items(.data)[@intFromEnum(inst_info.inst)].extended; | 3763 | const extended = zir.instructions.items(.data)[@intFromEnum(inst_info.inst)].extended; |
| ... | @@ -3851,8 +3829,7 @@ fn recreateUnionType( | ... | @@ -3851,8 +3829,7 @@ fn recreateUnionType( |
| 3851 | 3829 | ||
| 3852 | const inst_info = key.zir_index.resolveFull(ip).?; | 3830 | const inst_info = key.zir_index.resolveFull(ip).?; |
| 3853 | const file = zcu.fileByIndex(inst_info.file); | 3831 | const file = zcu.fileByIndex(inst_info.file); |
| 3854 | assert(file.status == .success_zir); // otherwise inst tracking failed | 3832 | const zir = file.zir.?; |
| 3855 | const zir = file.zir; | ||
| 3856 | 3833 | ||
| 3857 | assert(zir.instructions.items(.tag)[@intFromEnum(inst_info.inst)] == .extended); | 3834 | assert(zir.instructions.items(.tag)[@intFromEnum(inst_info.inst)] == .extended); |
| 3858 | const extended = zir.instructions.items(.data)[@intFromEnum(inst_info.inst)].extended; | 3835 | const extended = zir.instructions.items(.data)[@intFromEnum(inst_info.inst)].extended; |
| ... | @@ -3938,8 +3915,7 @@ fn recreateEnumType( | ... | @@ -3938,8 +3915,7 @@ fn recreateEnumType( |
| 3938 | 3915 | ||
| 3939 | const inst_info = key.zir_index.resolveFull(ip).?; | 3916 | const inst_info = key.zir_index.resolveFull(ip).?; |
| 3940 | const file = zcu.fileByIndex(inst_info.file); | 3917 | const file = zcu.fileByIndex(inst_info.file); |
| 3941 | assert(file.status == .success_zir); // otherwise inst tracking failed | 3918 | const zir = file.zir.?; |
| 3942 | const zir = file.zir; | ||
| 3943 | 3919 | ||
| 3944 | assert(zir.instructions.items(.tag)[@intFromEnum(inst_info.inst)] == .extended); | 3920 | assert(zir.instructions.items(.tag)[@intFromEnum(inst_info.inst)] == .extended); |
| 3945 | const extended = zir.instructions.items(.data)[@intFromEnum(inst_info.inst)].extended; | 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,8 +4058,7 @@ pub fn ensureNamespaceUpToDate(pt: Zcu.PerThread, namespace_index: Zcu.Namespace |
| 4082 | 4058 | ||
| 4083 | const inst_info = key.zir_index.resolveFull(ip) orelse return error.AnalysisFail; | 4059 | const inst_info = key.zir_index.resolveFull(ip) orelse return error.AnalysisFail; |
| 4084 | const file = zcu.fileByIndex(inst_info.file); | 4060 | const file = zcu.fileByIndex(inst_info.file); |
| 4085 | if (file.status != .success_zir) return error.AnalysisFail; | 4061 | const zir = file.zir.?; |
| 4086 | const zir = file.zir; | ||
| 4087 | 4062 | ||
| 4088 | assert(zir.instructions.items(.tag)[@intFromEnum(inst_info.inst)] == .extended); | 4063 | assert(zir.instructions.items(.tag)[@intFromEnum(inst_info.inst)] == .extended); |
| 4089 | const extended = zir.instructions.items(.data)[@intFromEnum(inst_info.inst)].extended; | 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,8 +750,7 @@ pub const File = struct { |
| 750 | { | 750 | { |
| 751 | const ti = ti_id.resolveFull(&pt.zcu.intern_pool).?; | 751 | const ti = ti_id.resolveFull(&pt.zcu.intern_pool).?; |
| 752 | const file = pt.zcu.fileByIndex(ti.file); | 752 | const file = pt.zcu.fileByIndex(ti.file); |
| 753 | assert(file.zir_loaded); | 753 | const inst = file.zir.?.instructions.get(@intFromEnum(ti.inst)); |
| 754 | const inst = file.zir.instructions.get(@intFromEnum(ti.inst)); | ||
| 755 | assert(inst.tag == .declaration); | 754 | assert(inst.tag == .declaration); |
| 756 | } | 755 | } |
| 757 | 756 |
src/link/Dwarf.zig+7-10| ... | @@ -2358,8 +2358,7 @@ fn initWipNavInner( | ... | @@ -2358,8 +2358,7 @@ fn initWipNavInner( |
| 2358 | const nav = ip.getNav(nav_index); | 2358 | const nav = ip.getNav(nav_index); |
| 2359 | const inst_info = nav.srcInst(ip).resolveFull(ip).?; | 2359 | const inst_info = nav.srcInst(ip).resolveFull(ip).?; |
| 2360 | const file = zcu.fileByIndex(inst_info.file); | 2360 | const file = zcu.fileByIndex(inst_info.file); |
| 2361 | assert(file.zir_loaded); | 2361 | const decl = file.zir.?.getDeclaration(inst_info.inst); |
| 2362 | const decl = file.zir.getDeclaration(inst_info.inst); | ||
| 2363 | log.debug("initWipNav({s}:{d}:{d} %{d} = {})", .{ | 2362 | log.debug("initWipNav({s}:{d}:{d} %{d} = {})", .{ |
| 2364 | file.sub_file_path, | 2363 | file.sub_file_path, |
| 2365 | decl.src_line + 1, | 2364 | decl.src_line + 1, |
| ... | @@ -2373,7 +2372,7 @@ fn initWipNavInner( | ... | @@ -2373,7 +2372,7 @@ fn initWipNavInner( |
| 2373 | switch (nav_key) { | 2372 | switch (nav_key) { |
| 2374 | // Ignore @extern | 2373 | // Ignore @extern |
| 2375 | .@"extern" => |@"extern"| if (decl.linkage != .@"extern" or | 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 | else => {}, | 2376 | else => {}, |
| 2378 | } | 2377 | } |
| 2379 | 2378 | ||
| ... | @@ -2696,8 +2695,7 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo | ... | @@ -2696,8 +2695,7 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo |
| 2696 | const nav = ip.getNav(nav_index); | 2695 | const nav = ip.getNav(nav_index); |
| 2697 | const inst_info = nav.srcInst(ip).resolveFull(ip).?; | 2696 | const inst_info = nav.srcInst(ip).resolveFull(ip).?; |
| 2698 | const file = zcu.fileByIndex(inst_info.file); | 2697 | const file = zcu.fileByIndex(inst_info.file); |
| 2699 | assert(file.zir_loaded); | 2698 | const decl = file.zir.?.getDeclaration(inst_info.inst); |
| 2700 | const decl = file.zir.getDeclaration(inst_info.inst); | ||
| 2701 | log.debug("updateComptimeNav({s}:{d}:{d} %{d} = {})", .{ | 2699 | log.debug("updateComptimeNav({s}:{d}:{d} %{d} = {})", .{ |
| 2702 | file.sub_file_path, | 2700 | file.sub_file_path, |
| 2703 | decl.src_line + 1, | 2701 | decl.src_line + 1, |
| ... | @@ -4097,7 +4095,7 @@ pub fn updateContainerType(dwarf: *Dwarf, pt: Zcu.PerThread, type_index: InternP | ... | @@ -4097,7 +4095,7 @@ pub fn updateContainerType(dwarf: *Dwarf, pt: Zcu.PerThread, type_index: InternP |
| 4097 | // if a newly-tracked instruction can be a type's owner `zir_index`. | 4095 | // if a newly-tracked instruction can be a type's owner `zir_index`. |
| 4098 | comptime assert(Zir.inst_tracking_version == 0); | 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 | const name_strat: Zir.Inst.NameStrategy = switch (decl_inst.tag) { | 4099 | const name_strat: Zir.Inst.NameStrategy = switch (decl_inst.tag) { |
| 4102 | .struct_init, .struct_init_ref, .struct_init_anon => .anon, | 4100 | .struct_init, .struct_init_ref, .struct_init_anon => .anon, |
| 4103 | .extended => switch (decl_inst.data.extended.opcode) { | 4101 | .extended => switch (decl_inst.data.extended.opcode) { |
| ... | @@ -4301,14 +4299,13 @@ pub fn updateLineNumber(dwarf: *Dwarf, zcu: *Zcu, zir_index: InternPool.TrackedI | ... | @@ -4301,14 +4299,13 @@ pub fn updateLineNumber(dwarf: *Dwarf, zcu: *Zcu, zir_index: InternPool.TrackedI |
| 4301 | const inst_info = zir_index.resolveFull(ip).?; | 4299 | const inst_info = zir_index.resolveFull(ip).?; |
| 4302 | assert(inst_info.inst != .main_struct_inst); | 4300 | assert(inst_info.inst != .main_struct_inst); |
| 4303 | const file = zcu.fileByIndex(inst_info.file); | 4301 | const file = zcu.fileByIndex(inst_info.file); |
| 4304 | assert(file.zir_loaded); | 4302 | const decl = file.zir.?.getDeclaration(inst_info.inst); |
| 4305 | const decl = file.zir.getDeclaration(inst_info.inst); | ||
| 4306 | log.debug("updateLineNumber({s}:{d}:{d} %{d} = {s})", .{ | 4303 | log.debug("updateLineNumber({s}:{d}:{d} %{d} = {s})", .{ |
| 4307 | file.sub_file_path, | 4304 | file.sub_file_path, |
| 4308 | decl.src_line + 1, | 4305 | decl.src_line + 1, |
| 4309 | decl.src_column + 1, | 4306 | decl.src_column + 1, |
| 4310 | @intFromEnum(inst_info.inst), | 4307 | @intFromEnum(inst_info.inst), |
| 4311 | file.zir.nullTerminatedString(decl.name), | 4308 | file.zir.?.nullTerminatedString(decl.name), |
| 4312 | }); | 4309 | }); |
| 4313 | 4310 | ||
| 4314 | var line_buf: [4]u8 = undefined; | 4311 | var line_buf: [4]u8 = undefined; |
| ... | @@ -4661,7 +4658,7 @@ pub fn flushModule(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void { | ... | @@ -4661,7 +4658,7 @@ pub fn flushModule(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void { |
| 4661 | .target_unit = StringSection.unit, | 4658 | .target_unit = StringSection.unit, |
| 4662 | .target_entry = (try dwarf.debug_line_str.addString( | 4659 | .target_entry = (try dwarf.debug_line_str.addString( |
| 4663 | dwarf, | 4660 | dwarf, |
| 4664 | if (file.mod.builtin_file == file) file.source else "", | 4661 | if (file.mod.builtin_file == file) file.source.? else "", |
| 4665 | )).toOptional(), | 4662 | )).toOptional(), |
| 4666 | }); | 4663 | }); |
| 4667 | header.appendNTimesAssumeCapacity(0, dwarf.sectionOffsetBytes()); | 4664 | header.appendNTimesAssumeCapacity(0, dwarf.sectionOffsetBytes()); |
src/main.zig+49-66| ... | @@ -3636,7 +3636,7 @@ fn buildOutputType( | ... | @@ -3636,7 +3636,7 @@ fn buildOutputType( |
| 3636 | 3636 | ||
| 3637 | if (show_builtin) { | 3637 | if (show_builtin) { |
| 3638 | const builtin_mod = comp.root_mod.getBuiltinDependency(); | 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 | return std.io.getStdOut().writeAll(source); | 3640 | return std.io.getStdOut().writeAll(source); |
| 3641 | } | 3641 | } |
| 3642 | switch (listen) { | 3642 | switch (listen) { |
| ... | @@ -6134,15 +6134,12 @@ fn cmdAstCheck( | ... | @@ -6134,15 +6134,12 @@ fn cmdAstCheck( |
| 6134 | 6134 | ||
| 6135 | var file: Zcu.File = .{ | 6135 | var file: Zcu.File = .{ |
| 6136 | .status = .never_loaded, | 6136 | .status = .never_loaded, |
| 6137 | .prev_status = .never_loaded, | ||
| 6138 | .source_loaded = false, | ||
| 6139 | .tree_loaded = false, | ||
| 6140 | .zir_loaded = false, | ||
| 6141 | .sub_file_path = undefined, | 6137 | .sub_file_path = undefined, |
| 6142 | .source = undefined, | ||
| 6143 | .stat = undefined, | 6138 | .stat = undefined, |
| 6144 | .tree = undefined, | 6139 | .source = null, |
| 6145 | .zir = undefined, | 6140 | .tree = null, |
| 6141 | .zir = null, | ||
| 6142 | .zoir = null, | ||
| 6146 | .mod = undefined, | 6143 | .mod = undefined, |
| 6147 | }; | 6144 | }; |
| 6148 | if (zig_source_file) |file_name| { | 6145 | if (zig_source_file) |file_name| { |
| ... | @@ -6163,7 +6160,6 @@ fn cmdAstCheck( | ... | @@ -6163,7 +6160,6 @@ fn cmdAstCheck( |
| 6163 | 6160 | ||
| 6164 | file.sub_file_path = file_name; | 6161 | file.sub_file_path = file_name; |
| 6165 | file.source = source; | 6162 | file.source = source; |
| 6166 | file.source_loaded = true; | ||
| 6167 | file.stat = .{ | 6163 | file.stat = .{ |
| 6168 | .size = stat.size, | 6164 | .size = stat.size, |
| 6169 | .inode = stat.inode, | 6165 | .inode = stat.inode, |
| ... | @@ -6176,7 +6172,6 @@ fn cmdAstCheck( | ... | @@ -6176,7 +6172,6 @@ fn cmdAstCheck( |
| 6176 | }; | 6172 | }; |
| 6177 | file.sub_file_path = "<stdin>"; | 6173 | file.sub_file_path = "<stdin>"; |
| 6178 | file.source = source; | 6174 | file.source = source; |
| 6179 | file.source_loaded = true; | ||
| 6180 | file.stat.size = source.len; | 6175 | file.stat.size = source.len; |
| 6181 | } | 6176 | } |
| 6182 | 6177 | ||
| ... | @@ -6196,17 +6191,15 @@ fn cmdAstCheck( | ... | @@ -6196,17 +6191,15 @@ fn cmdAstCheck( |
| 6196 | .fully_qualified_name = "root", | 6191 | .fully_qualified_name = "root", |
| 6197 | }); | 6192 | }); |
| 6198 | 6193 | ||
| 6199 | file.tree = try Ast.parse(gpa, file.source, mode); | 6194 | file.tree = try Ast.parse(gpa, file.source.?, mode); |
| 6200 | file.tree_loaded = true; | 6195 | defer file.tree.?.deinit(gpa); |
| 6201 | defer file.tree.deinit(gpa); | ||
| 6202 | 6196 | ||
| 6203 | switch (mode) { | 6197 | switch (mode) { |
| 6204 | .zig => { | 6198 | .zig => { |
| 6205 | file.zir = try AstGen.generate(gpa, file.tree); | 6199 | file.zir = try AstGen.generate(gpa, file.tree.?); |
| 6206 | file.zir_loaded = true; | 6200 | defer file.zir.?.deinit(gpa); |
| 6207 | defer file.zir.deinit(gpa); | ||
| 6208 | 6201 | ||
| 6209 | if (file.zir.hasCompileErrors()) { | 6202 | if (file.zir.?.hasCompileErrors()) { |
| 6210 | var wip_errors: std.zig.ErrorBundle.Wip = undefined; | 6203 | var wip_errors: std.zig.ErrorBundle.Wip = undefined; |
| 6211 | try wip_errors.init(gpa); | 6204 | try wip_errors.init(gpa); |
| 6212 | defer wip_errors.deinit(); | 6205 | defer wip_errors.deinit(); |
| ... | @@ -6215,13 +6208,13 @@ fn cmdAstCheck( | ... | @@ -6215,13 +6208,13 @@ fn cmdAstCheck( |
| 6215 | defer error_bundle.deinit(gpa); | 6208 | defer error_bundle.deinit(gpa); |
| 6216 | error_bundle.renderToStdErr(color.renderOptions()); | 6209 | error_bundle.renderToStdErr(color.renderOptions()); |
| 6217 | 6210 | ||
| 6218 | if (file.zir.loweringFailed()) { | 6211 | if (file.zir.?.loweringFailed()) { |
| 6219 | process.exit(1); | 6212 | process.exit(1); |
| 6220 | } | 6213 | } |
| 6221 | } | 6214 | } |
| 6222 | 6215 | ||
| 6223 | if (!want_output_text) { | 6216 | if (!want_output_text) { |
| 6224 | if (file.zir.hasCompileErrors()) { | 6217 | if (file.zir.?.hasCompileErrors()) { |
| 6225 | process.exit(1); | 6218 | process.exit(1); |
| 6226 | } else { | 6219 | } else { |
| 6227 | return cleanExit(); | 6220 | return cleanExit(); |
| ... | @@ -6233,18 +6226,18 @@ fn cmdAstCheck( | ... | @@ -6233,18 +6226,18 @@ fn cmdAstCheck( |
| 6233 | 6226 | ||
| 6234 | { | 6227 | { |
| 6235 | const token_bytes = @sizeOf(Ast.TokenList) + | 6228 | const token_bytes = @sizeOf(Ast.TokenList) + |
| 6236 | file.tree.tokens.len * (@sizeOf(std.zig.Token.Tag) + @sizeOf(Ast.ByteOffset)); | 6229 | file.tree.?.tokens.len * (@sizeOf(std.zig.Token.Tag) + @sizeOf(Ast.ByteOffset)); |
| 6237 | const tree_bytes = @sizeOf(Ast) + file.tree.nodes.len * | 6230 | const tree_bytes = @sizeOf(Ast) + file.tree.?.nodes.len * |
| 6238 | (@sizeOf(Ast.Node.Tag) + | 6231 | (@sizeOf(Ast.Node.Tag) + |
| 6239 | @sizeOf(Ast.Node.Data) + | 6232 | @sizeOf(Ast.Node.Data) + |
| 6240 | @sizeOf(Ast.TokenIndex)); | 6233 | @sizeOf(Ast.TokenIndex)); |
| 6241 | const instruction_bytes = file.zir.instructions.len * | 6234 | const instruction_bytes = file.zir.?.instructions.len * |
| 6242 | // Here we don't use @sizeOf(Zir.Inst.Data) because it would include | 6235 | // Here we don't use @sizeOf(Zir.Inst.Data) because it would include |
| 6243 | // the debug safety tag but we want to measure release size. | 6236 | // the debug safety tag but we want to measure release size. |
| 6244 | (@sizeOf(Zir.Inst.Tag) + 8); | 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 | const total_bytes = @sizeOf(Zir) + instruction_bytes + extra_bytes + | 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 | const stdout = io.getStdOut(); | 6241 | const stdout = io.getStdOut(); |
| 6249 | const fmtIntSizeBin = std.fmt.fmtIntSizeBin; | 6242 | const fmtIntSizeBin = std.fmt.fmtIntSizeBin; |
| 6250 | // zig fmt: off | 6243 | // zig fmt: off |
| ... | @@ -6258,27 +6251,27 @@ fn cmdAstCheck( | ... | @@ -6258,27 +6251,27 @@ fn cmdAstCheck( |
| 6258 | \\# Extra Data Items: {d} ({}) | 6251 | \\# Extra Data Items: {d} ({}) |
| 6259 | \\ | 6252 | \\ |
| 6260 | , .{ | 6253 | , .{ |
| 6261 | fmtIntSizeBin(file.source.len), | 6254 | fmtIntSizeBin(file.source.?.len), |
| 6262 | file.tree.tokens.len, fmtIntSizeBin(token_bytes), | 6255 | file.tree.?.tokens.len, fmtIntSizeBin(token_bytes), |
| 6263 | file.tree.nodes.len, fmtIntSizeBin(tree_bytes), | 6256 | file.tree.?.nodes.len, fmtIntSizeBin(tree_bytes), |
| 6264 | fmtIntSizeBin(total_bytes), | 6257 | fmtIntSizeBin(total_bytes), |
| 6265 | file.zir.instructions.len, fmtIntSizeBin(instruction_bytes), | 6258 | file.zir.?.instructions.len, fmtIntSizeBin(instruction_bytes), |
| 6266 | fmtIntSizeBin(file.zir.string_bytes.len), | 6259 | fmtIntSizeBin(file.zir.?.string_bytes.len), |
| 6267 | file.zir.extra.len, fmtIntSizeBin(extra_bytes), | 6260 | file.zir.?.extra.len, fmtIntSizeBin(extra_bytes), |
| 6268 | }); | 6261 | }); |
| 6269 | // zig fmt: on | 6262 | // zig fmt: on |
| 6270 | } | 6263 | } |
| 6271 | 6264 | ||
| 6272 | try @import("print_zir.zig").renderAsTextToFile(gpa, &file, io.getStdOut()); | 6265 | try @import("print_zir.zig").renderAsTextToFile(gpa, &file, io.getStdOut()); |
| 6273 | 6266 | ||
| 6274 | if (file.zir.hasCompileErrors()) { | 6267 | if (file.zir.?.hasCompileErrors()) { |
| 6275 | process.exit(1); | 6268 | process.exit(1); |
| 6276 | } else { | 6269 | } else { |
| 6277 | return cleanExit(); | 6270 | return cleanExit(); |
| 6278 | } | 6271 | } |
| 6279 | }, | 6272 | }, |
| 6280 | .zon => { | 6273 | .zon => { |
| 6281 | const zoir = try ZonGen.generate(gpa, file.tree, .{}); | 6274 | const zoir = try ZonGen.generate(gpa, file.tree.?, .{}); |
| 6282 | defer zoir.deinit(gpa); | 6275 | defer zoir.deinit(gpa); |
| 6283 | 6276 | ||
| 6284 | if (zoir.hasCompileErrors()) { | 6277 | if (zoir.hasCompileErrors()) { |
| ... | @@ -6289,7 +6282,7 @@ fn cmdAstCheck( | ... | @@ -6289,7 +6282,7 @@ fn cmdAstCheck( |
| 6289 | { | 6282 | { |
| 6290 | const src_path = try file.fullPath(gpa); | 6283 | const src_path = try file.fullPath(gpa); |
| 6291 | defer gpa.free(src_path); | 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 | var error_bundle = try wip_errors.toOwnedBundle(""); | 6288 | var error_bundle = try wip_errors.toOwnedBundle(""); |
| ... | @@ -6518,27 +6511,24 @@ fn cmdDumpZir( | ... | @@ -6518,27 +6511,24 @@ fn cmdDumpZir( |
| 6518 | 6511 | ||
| 6519 | var file: Zcu.File = .{ | 6512 | var file: Zcu.File = .{ |
| 6520 | .status = .never_loaded, | 6513 | .status = .never_loaded, |
| 6521 | .prev_status = .never_loaded, | ||
| 6522 | .source_loaded = false, | ||
| 6523 | .tree_loaded = false, | ||
| 6524 | .zir_loaded = true, | ||
| 6525 | .sub_file_path = undefined, | 6514 | .sub_file_path = undefined, |
| 6526 | .source = undefined, | ||
| 6527 | .stat = undefined, | 6515 | .stat = undefined, |
| 6528 | .tree = undefined, | 6516 | .source = null, |
| 6517 | .tree = null, | ||
| 6529 | .zir = try Zcu.loadZirCache(gpa, f), | 6518 | .zir = try Zcu.loadZirCache(gpa, f), |
| 6519 | .zoir = null, | ||
| 6530 | .mod = undefined, | 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 | // Here we don't use @sizeOf(Zir.Inst.Data) because it would include | 6526 | // Here we don't use @sizeOf(Zir.Inst.Data) because it would include |
| 6537 | // the debug safety tag but we want to measure release size. | 6527 | // the debug safety tag but we want to measure release size. |
| 6538 | (@sizeOf(Zir.Inst.Tag) + 8); | 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 | const total_bytes = @sizeOf(Zir) + instruction_bytes + extra_bytes + | 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 | const stdout = io.getStdOut(); | 6532 | const stdout = io.getStdOut(); |
| 6543 | const fmtIntSizeBin = std.fmt.fmtIntSizeBin; | 6533 | const fmtIntSizeBin = std.fmt.fmtIntSizeBin; |
| 6544 | // zig fmt: off | 6534 | // zig fmt: off |
| ... | @@ -6550,9 +6540,9 @@ fn cmdDumpZir( | ... | @@ -6550,9 +6540,9 @@ fn cmdDumpZir( |
| 6550 | \\ | 6540 | \\ |
| 6551 | , .{ | 6541 | , .{ |
| 6552 | fmtIntSizeBin(total_bytes), | 6542 | fmtIntSizeBin(total_bytes), |
| 6553 | file.zir.instructions.len, fmtIntSizeBin(instruction_bytes), | 6543 | file.zir.?.instructions.len, fmtIntSizeBin(instruction_bytes), |
| 6554 | fmtIntSizeBin(file.zir.string_bytes.len), | 6544 | fmtIntSizeBin(file.zir.?.string_bytes.len), |
| 6555 | file.zir.extra.len, fmtIntSizeBin(extra_bytes), | 6545 | file.zir.?.extra.len, fmtIntSizeBin(extra_bytes), |
| 6556 | }); | 6546 | }); |
| 6557 | // zig fmt: on | 6547 | // zig fmt: on |
| 6558 | } | 6548 | } |
| ... | @@ -6586,19 +6576,16 @@ fn cmdChangelist( | ... | @@ -6586,19 +6576,16 @@ fn cmdChangelist( |
| 6586 | 6576 | ||
| 6587 | var file: Zcu.File = .{ | 6577 | var file: Zcu.File = .{ |
| 6588 | .status = .never_loaded, | 6578 | .status = .never_loaded, |
| 6589 | .prev_status = .never_loaded, | ||
| 6590 | .source_loaded = false, | ||
| 6591 | .tree_loaded = false, | ||
| 6592 | .zir_loaded = false, | ||
| 6593 | .sub_file_path = old_source_file, | 6579 | .sub_file_path = old_source_file, |
| 6594 | .source = undefined, | ||
| 6595 | .stat = .{ | 6580 | .stat = .{ |
| 6596 | .size = stat.size, | 6581 | .size = stat.size, |
| 6597 | .inode = stat.inode, | 6582 | .inode = stat.inode, |
| 6598 | .mtime = stat.mtime, | 6583 | .mtime = stat.mtime, |
| 6599 | }, | 6584 | }, |
| 6600 | .tree = undefined, | 6585 | .source = null, |
| 6601 | .zir = undefined, | 6586 | .tree = null, |
| 6587 | .zir = null, | ||
| 6588 | .zoir = null, | ||
| 6602 | .mod = undefined, | 6589 | .mod = undefined, |
| 6603 | }; | 6590 | }; |
| 6604 | 6591 | ||
| ... | @@ -6613,17 +6600,14 @@ fn cmdChangelist( | ... | @@ -6613,17 +6600,14 @@ fn cmdChangelist( |
| 6613 | if (amt != stat.size) | 6600 | if (amt != stat.size) |
| 6614 | return error.UnexpectedEndOfFile; | 6601 | return error.UnexpectedEndOfFile; |
| 6615 | file.source = source; | 6602 | file.source = source; |
| 6616 | file.source_loaded = true; | ||
| 6617 | 6603 | ||
| 6618 | file.tree = try Ast.parse(gpa, file.source, .zig); | 6604 | file.tree = try Ast.parse(gpa, file.source.?, .zig); |
| 6619 | file.tree_loaded = true; | 6605 | defer file.tree.?.deinit(gpa); |
| 6620 | defer file.tree.deinit(gpa); | ||
| 6621 | 6606 | ||
| 6622 | file.zir = try AstGen.generate(gpa, file.tree); | 6607 | file.zir = try AstGen.generate(gpa, file.tree.?); |
| 6623 | file.zir_loaded = true; | 6608 | defer file.zir.?.deinit(gpa); |
| 6624 | defer file.zir.deinit(gpa); | ||
| 6625 | 6609 | ||
| 6626 | if (file.zir.loweringFailed()) { | 6610 | if (file.zir.?.loweringFailed()) { |
| 6627 | var wip_errors: std.zig.ErrorBundle.Wip = undefined; | 6611 | var wip_errors: std.zig.ErrorBundle.Wip = undefined; |
| 6628 | try wip_errors.init(gpa); | 6612 | try wip_errors.init(gpa); |
| 6629 | defer wip_errors.deinit(); | 6613 | defer wip_errors.deinit(); |
| ... | @@ -6652,13 +6636,12 @@ fn cmdChangelist( | ... | @@ -6652,13 +6636,12 @@ fn cmdChangelist( |
| 6652 | var new_tree = try Ast.parse(gpa, new_source, .zig); | 6636 | var new_tree = try Ast.parse(gpa, new_source, .zig); |
| 6653 | defer new_tree.deinit(gpa); | 6637 | defer new_tree.deinit(gpa); |
| 6654 | 6638 | ||
| 6655 | var old_zir = file.zir; | 6639 | var old_zir = file.zir.?; |
| 6656 | defer old_zir.deinit(gpa); | 6640 | defer old_zir.deinit(gpa); |
| 6657 | file.zir_loaded = false; | 6641 | file.zir = null; |
| 6658 | file.zir = try AstGen.generate(gpa, new_tree); | 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 | var wip_errors: std.zig.ErrorBundle.Wip = undefined; | 6645 | var wip_errors: std.zig.ErrorBundle.Wip = undefined; |
| 6663 | try wip_errors.init(gpa); | 6646 | try wip_errors.init(gpa); |
| 6664 | defer wip_errors.deinit(); | 6647 | defer wip_errors.deinit(); |
| ... | @@ -6672,7 +6655,7 @@ fn cmdChangelist( | ... | @@ -6672,7 +6655,7 @@ fn cmdChangelist( |
| 6672 | var inst_map: std.AutoHashMapUnmanaged(Zir.Inst.Index, Zir.Inst.Index) = .empty; | 6655 | var inst_map: std.AutoHashMapUnmanaged(Zir.Inst.Index, Zir.Inst.Index) = .empty; |
| 6673 | defer inst_map.deinit(gpa); | 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 | var bw = io.bufferedWriter(io.getStdOut().writer()); | 6660 | var bw = io.bufferedWriter(io.getStdOut().writer()); |
| 6678 | const stdout = bw.writer(); | 6661 | const stdout = bw.writer(); |
src/print_zir.zig+10-13| ... | @@ -22,7 +22,7 @@ pub fn renderAsTextToFile( | ... | @@ -22,7 +22,7 @@ pub fn renderAsTextToFile( |
| 22 | .gpa = gpa, | 22 | .gpa = gpa, |
| 23 | .arena = arena.allocator(), | 23 | .arena = arena.allocator(), |
| 24 | .file = scope_file, | 24 | .file = scope_file, |
| 25 | .code = scope_file.zir, | 25 | .code = scope_file.zir.?, |
| 26 | .indent = 0, | 26 | .indent = 0, |
| 27 | .parent_decl_node = 0, | 27 | .parent_decl_node = 0, |
| 28 | .recurse_decls = true, | 28 | .recurse_decls = true, |
| ... | @@ -36,18 +36,18 @@ pub fn renderAsTextToFile( | ... | @@ -36,18 +36,18 @@ pub fn renderAsTextToFile( |
| 36 | try stream.print("%{d} ", .{@intFromEnum(main_struct_inst)}); | 36 | try stream.print("%{d} ", .{@intFromEnum(main_struct_inst)}); |
| 37 | try writer.writeInstToStream(stream, main_struct_inst); | 37 | try writer.writeInstToStream(stream, main_struct_inst); |
| 38 | try stream.writeAll("\n"); | 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 | if (imports_index != 0) { | 40 | if (imports_index != 0) { |
| 41 | try stream.writeAll("Imports:\n"); | 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 | var extra_index = extra.end; | 44 | var extra_index = extra.end; |
| 45 | 45 | ||
| 46 | for (0..extra.data.imports_len) |_| { | 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 | extra_index = item.end; | 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 | try stream.print(" @import(\"{}\") ", .{ | 51 | try stream.print(" @import(\"{}\") ", .{ |
| 52 | std.zig.fmtEscapes(import_path), | 52 | std.zig.fmtEscapes(import_path), |
| 53 | }); | 53 | }); |
| ... | @@ -75,7 +75,7 @@ pub fn renderInstructionContext( | ... | @@ -75,7 +75,7 @@ pub fn renderInstructionContext( |
| 75 | .gpa = gpa, | 75 | .gpa = gpa, |
| 76 | .arena = arena.allocator(), | 76 | .arena = arena.allocator(), |
| 77 | .file = scope_file, | 77 | .file = scope_file, |
| 78 | .code = scope_file.zir, | 78 | .code = scope_file.zir.?, |
| 79 | .indent = if (indent < 2) 2 else indent, | 79 | .indent = if (indent < 2) 2 else indent, |
| 80 | .parent_decl_node = parent_decl_node, | 80 | .parent_decl_node = parent_decl_node, |
| 81 | .recurse_decls = false, | 81 | .recurse_decls = false, |
| ... | @@ -107,7 +107,7 @@ pub fn renderSingleInstruction( | ... | @@ -107,7 +107,7 @@ pub fn renderSingleInstruction( |
| 107 | .gpa = gpa, | 107 | .gpa = gpa, |
| 108 | .arena = arena.allocator(), | 108 | .arena = arena.allocator(), |
| 109 | .file = scope_file, | 109 | .file = scope_file, |
| 110 | .code = scope_file.zir, | 110 | .code = scope_file.zir.?, |
| 111 | .indent = indent, | 111 | .indent = indent, |
| 112 | .parent_decl_node = parent_decl_node, | 112 | .parent_decl_node = parent_decl_node, |
| 113 | .recurse_decls = false, | 113 | .recurse_decls = false, |
| ... | @@ -2759,8 +2759,7 @@ const Writer = struct { | ... | @@ -2759,8 +2759,7 @@ const Writer = struct { |
| 2759 | } | 2759 | } |
| 2760 | 2760 | ||
| 2761 | fn writeSrcNode(self: *Writer, stream: anytype, src_node: i32) !void { | 2761 | fn writeSrcNode(self: *Writer, stream: anytype, src_node: i32) !void { |
| 2762 | if (!self.file.tree_loaded) return; | 2762 | const tree = self.file.tree orelse return; |
| 2763 | const tree = self.file.tree; | ||
| 2764 | const abs_node = self.relativeToNodeIndex(src_node); | 2763 | const abs_node = self.relativeToNodeIndex(src_node); |
| 2765 | const src_span = tree.nodeToSpan(abs_node); | 2764 | const src_span = tree.nodeToSpan(abs_node); |
| 2766 | const start = self.line_col_cursor.find(tree.source, src_span.start); | 2765 | const start = self.line_col_cursor.find(tree.source, src_span.start); |
| ... | @@ -2772,8 +2771,7 @@ const Writer = struct { | ... | @@ -2772,8 +2771,7 @@ const Writer = struct { |
| 2772 | } | 2771 | } |
| 2773 | 2772 | ||
| 2774 | fn writeSrcTok(self: *Writer, stream: anytype, src_tok: u32) !void { | 2773 | fn writeSrcTok(self: *Writer, stream: anytype, src_tok: u32) !void { |
| 2775 | if (!self.file.tree_loaded) return; | 2774 | const tree = self.file.tree orelse return; |
| 2776 | const tree = self.file.tree; | ||
| 2777 | const abs_tok = tree.firstToken(self.parent_decl_node) + src_tok; | 2775 | const abs_tok = tree.firstToken(self.parent_decl_node) + src_tok; |
| 2778 | const span_start = tree.tokens.items(.start)[abs_tok]; | 2776 | const span_start = tree.tokens.items(.start)[abs_tok]; |
| 2779 | const span_end = span_start + @as(u32, @intCast(tree.tokenSlice(abs_tok).len)); | 2777 | const span_end = span_start + @as(u32, @intCast(tree.tokenSlice(abs_tok).len)); |
| ... | @@ -2786,8 +2784,7 @@ const Writer = struct { | ... | @@ -2786,8 +2784,7 @@ const Writer = struct { |
| 2786 | } | 2784 | } |
| 2787 | 2785 | ||
| 2788 | fn writeSrcTokAbs(self: *Writer, stream: anytype, src_tok: u32) !void { | 2786 | fn writeSrcTokAbs(self: *Writer, stream: anytype, src_tok: u32) !void { |
| 2789 | if (!self.file.tree_loaded) return; | 2787 | const tree = self.file.tree orelse return; |
| 2790 | const tree = self.file.tree; | ||
| 2791 | const span_start = tree.tokens.items(.start)[src_tok]; | 2788 | const span_start = tree.tokens.items(.start)[src_tok]; |
| 2792 | const span_end = span_start + @as(u32, @intCast(tree.tokenSlice(src_tok).len)); | 2789 | const span_end = span_start + @as(u32, @intCast(tree.tokenSlice(src_tok).len)); |
| 2793 | const start = self.line_col_cursor.find(tree.source, span_start); | 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" | ||