diff --git a/BRANCH_TODO b/BRANCH_TODO index c24172727d..83f973cad6 100644 --- a/BRANCH_TODO +++ b/BRANCH_TODO @@ -1,15 +1,10 @@ - * nested function decl: how to refer to params? - * look for cached zir code - * save zir code to cache * keep track of file dependencies/dependants * unload files from memory when a dependency is dropped - * implement zir error notes * implement the new AstGen compile errors * get rid of failed_root_src_file * get rid of Scope.DeclRef - * get rid of optional_type_from_ptr_elem * handle decl collision with usingnamespace * the decl doing the looking up needs to create a decl dependency on each usingnamespace decl @@ -38,6 +33,9 @@ AstGen can report more than one compile error. * AstGen: add result location pointers to function calls + * nested function decl: how to refer to params? + + * detect when to put cached ZIR into the local cache instead of the global one const container_name_hash: Scope.NameHash = if (found_pkg) |pkg| pkg.namespace_hash diff --git a/lib/std/fs/file.zig b/lib/std/fs/file.zig index 7a1737417d..a76652ffc9 100644 --- a/lib/std/fs/file.zig +++ b/lib/std/fs/file.zig @@ -482,7 +482,7 @@ pub const File = struct { /// order to handle partial reads from the underlying OS layer. /// See https://github.com/ziglang/zig/issues/7699 pub fn readvAll(self: File, iovecs: []os.iovec) ReadError!usize { - if (iovecs.len == 0) return; + if (iovecs.len == 0) return 0; var i: usize = 0; var off: usize = 0; diff --git a/src/Compilation.zig b/src/Compilation.zig index be488a20d6..684eef47e8 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -434,10 +434,10 @@ pub const AllErrors = struct { arena: *Allocator, errors: *std.ArrayList(Message), file: *Module.Scope.File, - source: []const u8, ) !void { assert(file.zir_loaded); assert(file.tree_loaded); + assert(file.source_loaded); const payload_index = file.zir.extra[@enumToInt(Zir.ExtraIndex.compile_errors)]; assert(payload_index != 0); @@ -466,7 +466,7 @@ pub const AllErrors = struct { } break :blk token_starts[note_item.data.token] + note_item.data.byte_offset; }; - const loc = std.zig.findLineColumn(source, byte_offset); + const loc = std.zig.findLineColumn(file.source, byte_offset); note.* = .{ .src = .{ @@ -492,7 +492,7 @@ pub const AllErrors = struct { } break :blk token_starts[item.data.token] + item.data.byte_offset; }; - const loc = std.zig.findLineColumn(source, byte_offset); + const loc = std.zig.findLineColumn(file.source, byte_offset); try errors.append(.{ .src = .{ @@ -1709,9 +1709,11 @@ pub fn getAllErrorsAlloc(self: *Compilation) !AllErrors { if (entry.value) |msg| { try AllErrors.add(module, &arena, &errors, msg.*); } else { - // Must be ZIR errors. - const source = try entry.key.getSource(module.gpa); - try AllErrors.addZir(&arena.allocator, &errors, entry.key, source); + // Must be ZIR errors. In order for ZIR errors to exist, the parsing + // must have completed successfully. + const tree = try entry.key.getTree(module.gpa); + assert(tree.errors.len == 0); + try AllErrors.addZir(&arena.allocator, &errors, entry.key); } } for (module.failed_decls.items()) |entry| { diff --git a/src/Module.zig b/src/Module.zig index ef5ecc934d..c321701be7 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -15,6 +15,7 @@ const ast = std.zig.ast; const Module = @This(); const Compilation = @import("Compilation.zig"); +const Cache = @import("Cache.zig"); const Value = @import("value.zig").Value; const Type = @import("type.zig").Type; const TypedValue = @import("TypedValue.zig"); @@ -771,6 +772,15 @@ pub const Scope = struct { return source; } + pub fn getTree(file: *File, gpa: *Allocator) !*const ast.Tree { + if (file.tree_loaded) return &file.tree; + + const source = try file.getSource(gpa); + file.tree = try std.zig.parse(gpa, source); + file.tree_loaded = true; + return &file.tree; + } + pub fn destroy(file: *File, gpa: *Allocator) void { file.deinit(gpa); gpa.destroy(file); @@ -2676,6 +2686,20 @@ fn freeExportList(gpa: *Allocator, export_list: []*Export) void { gpa.free(export_list); } +const data_has_safety_tag = @sizeOf(Zir.Inst.Data) != 8; +// TODO This is taking advantage of matching stage1 debug union layout. +// We need a better language feature for initializing a union with +// a runtime known tag. +const Stage1DataLayout = extern struct { + safety_tag: u8, + data: [8]u8 align(8), +}; +comptime { + if (data_has_safety_tag) { + assert(@sizeOf(Stage1DataLayout) == @sizeOf(Zir.Inst.Data)); + } +} + pub fn astGenFile(mod: *Module, file: *Scope.File, prog_node: *std.Progress.Node) !void { const tracy = trace(@src()); defer tracy.end(); @@ -2684,15 +2708,166 @@ pub fn astGenFile(mod: *Module, file: *Scope.File, prog_node: *std.Progress.Node const gpa = mod.gpa; // In any case we need to examine the stat of the file to determine the course of action. - var f = try file.pkg.root_src_directory.handle.openFile(file.sub_file_path, .{}); - defer f.close(); + var source_file = try file.pkg.root_src_directory.handle.openFile(file.sub_file_path, .{}); + defer source_file.close(); - const stat = try f.stat(); + const stat = try source_file.stat(); + + const want_local_cache = file.pkg == mod.root_pkg; + const digest = hash: { + var path_hash: Cache.HashHelper = .{}; + if (!want_local_cache) { + path_hash.addOptionalBytes(file.pkg.root_src_directory.path); + } + path_hash.addBytes(file.sub_file_path); + break :hash path_hash.final(); + }; + const cache_directory = if (want_local_cache) + comp.local_cache_directory + else + comp.global_cache_directory; + + var cache_file: ?std.fs.File = null; + defer if (cache_file) |f| f.close(); + + // TODO do this before spawning astgen workers + var zir_dir = try cache_directory.handle.makeOpenPath("z", .{}); + defer zir_dir.close(); // Determine whether we need to reload the file from disk and redo parsing and AstGen. switch (file.status) { - .never_loaded, .retryable_failure => { - log.debug("first-time AstGen: {s}", .{file.sub_file_path}); + .never_loaded, .retryable_failure => cached: { + // First, load the cached ZIR code, if any. + log.debug("AstGen checking cache: {s} (local={}, digest={s})", .{ + file.sub_file_path, want_local_cache, &digest, + }); + + // We ask for a lock in order to coordinate with other zig processes. + // If another process is already working on this file, we will get the cached + // version. Likewise if we're working on AstGen and another process asks for + // the cached file, they'll get it. + cache_file = zir_dir.openFile(&digest, .{ .lock = .Shared }) catch |err| switch (err) { + error.PathAlreadyExists => unreachable, // opening for reading + error.NoSpaceLeft => unreachable, // opening for reading + error.NotDir => unreachable, // no dir components + error.InvalidUtf8 => unreachable, // it's a hex encoded name + error.BadPathName => unreachable, // it's a hex encoded name + error.NameTooLong => unreachable, // it's a fixed size name + error.PipeBusy => unreachable, // it's not a pipe + error.WouldBlock => unreachable, // not asking for non-blocking I/O + + error.SymLinkLoop, + error.FileNotFound, + error.Unexpected, + => break :cached, + + else => |e| return e, // Retryable errors are handled at callsite. + }; + + // First we read the header to determine the lengths of arrays. + const header = cache_file.?.reader().readStruct(Zir.Header) catch |err| switch (err) { + // This can happen if Zig bails out of this function between creating + // the cached file and writing it. + error.EndOfStream => break :cached, + else => |e| return e, + }; + const unchanged_metadata = + stat.size == header.stat_size and + stat.mtime == header.stat_mtime and + stat.inode == header.stat_inode; + + if (!unchanged_metadata) { + log.debug("AstGen cache stale: {s}", .{file.sub_file_path}); + break :cached; + } + log.debug("AstGen cache hit: {s}", .{file.sub_file_path}); + + var instructions: std.MultiArrayList(Zir.Inst) = .{}; + defer instructions.deinit(gpa); + + try instructions.resize(gpa, header.instructions_len); + + var zir: Zir = .{ + .instructions = instructions.toOwnedSlice(), + .string_bytes = &.{}, + .extra = &.{}, + }; + var keep_zir = false; + defer if (!keep_zir) zir.deinit(gpa); + + zir.string_bytes = try gpa.alloc(u8, header.string_bytes_len); + zir.extra = try gpa.alloc(u32, header.extra_len); + + const safety_buffer = if (data_has_safety_tag) + try gpa.alloc([8]u8, header.instructions_len) + else + undefined; + defer if (data_has_safety_tag) gpa.free(safety_buffer); + + const data_ptr = if (data_has_safety_tag) + @ptrCast([*]u8, safety_buffer.ptr) + else + @ptrCast([*]u8, zir.instructions.items(.data).ptr); + + var iovecs = [_]std.os.iovec{ + .{ + .iov_base = @ptrCast([*]u8, zir.instructions.items(.tag).ptr), + .iov_len = header.instructions_len, + }, + .{ + .iov_base = data_ptr, + .iov_len = header.instructions_len * 8, + }, + .{ + .iov_base = zir.string_bytes.ptr, + .iov_len = header.string_bytes_len, + }, + .{ + .iov_base = @ptrCast([*]u8, zir.extra.ptr), + .iov_len = header.extra_len * 4, + }, + }; + const amt_read = try cache_file.?.readvAll(&iovecs); + const amt_expected = zir.instructions.len * 9 + + zir.string_bytes.len + + zir.extra.len * 4; + if (amt_read != amt_expected) { + log.warn("unexpected EOF reading cached ZIR for {s}", .{file.sub_file_path}); + zir.deinit(gpa); + break :cached; + } + if (data_has_safety_tag) { + const tags = zir.instructions.items(.tag); + for (zir.instructions.items(.data)) |*data, i| { + const union_tag = Zir.Inst.Tag.data_tags[@enumToInt(tags[i])]; + const as_struct = @ptrCast(*Stage1DataLayout, data); + as_struct.* = .{ + .safety_tag = @enumToInt(union_tag), + .data = safety_buffer[i], + }; + } + } + + keep_zir = true; + file.zir = zir; + file.zir_loaded = true; + file.stat_size = header.stat_size; + file.stat_inode = header.stat_inode; + file.stat_mtime = header.stat_mtime; + file.status = .success; + log.debug("AstGen cached success: {s}", .{file.sub_file_path}); + + // TODO don't report compile errors until Sema @importFile + if (file.zir.hasCompileErrors()) { + { + const lock = comp.mutex.acquire(); + defer lock.release(); + try mod.failed_files.putNoClobber(gpa, file, null); + } + file.status = .astgen_failure; + return error.AnalysisFail; + } + return; }, .parse_failure, .astgen_failure, .success => { const unchanged_metadata = @@ -2708,6 +2883,29 @@ pub fn astGenFile(mod: *Module, file: *Scope.File, prog_node: *std.Progress.Node log.debug("metadata changed: {s}", .{file.sub_file_path}); }, } + if (cache_file) |f| { + f.close(); + cache_file = null; + } + cache_file = zir_dir.createFile(&digest, .{ .lock = .Exclusive }) catch |err| switch (err) { + error.NotDir => unreachable, // no dir components + error.InvalidUtf8 => unreachable, // it's a hex encoded name + error.BadPathName => unreachable, // it's a hex encoded name + error.NameTooLong => unreachable, // it's a fixed size name + error.PipeBusy => unreachable, // it's not a pipe + error.WouldBlock => unreachable, // not asking for non-blocking I/O + error.FileNotFound => unreachable, // no dir components + + else => |e| { + const pkg_path = file.pkg.root_src_directory.path orelse "."; + const cache_path = cache_directory.path orelse "."; + log.warn("unable to save cached ZIR code for {s}/{s} to {s}/z/{s}: {s}", .{ + pkg_path, file.sub_file_path, cache_path, &digest, @errorName(e), + }); + return; + }, + }; + // Clear compile error for this file. switch (file.status) { .success, .retryable_failure => {}, @@ -2726,7 +2924,7 @@ pub fn astGenFile(mod: *Module, file: *Scope.File, prog_node: *std.Progress.Node const source = try gpa.allocSentinel(u8, stat.size, 0); defer if (!file.source_loaded) gpa.free(source); - const amt = try f.readAll(source); + const amt = try source_file.readAll(source); if (amt != stat.size) return error.UnexpectedEndOfFile; @@ -2770,7 +2968,67 @@ pub fn astGenFile(mod: *Module, file: *Scope.File, prog_node: *std.Progress.Node file.zir = try AstGen.generate(gpa, file); file.zir_loaded = true; + file.status = .success; + log.debug("AstGen fresh success: {s}", .{file.sub_file_path}); + const safety_buffer = if (data_has_safety_tag) + try gpa.alloc([8]u8, file.zir.instructions.len) + else + undefined; + defer if (data_has_safety_tag) gpa.free(safety_buffer); + const data_ptr = if (data_has_safety_tag) + @ptrCast([*]const u8, safety_buffer.ptr) + else + @ptrCast([*]const u8, file.zir.instructions.items(.data).ptr); + if (data_has_safety_tag) { + // The `Data` union has a safety tag but in the file format we store it without. + const tags = file.zir.instructions.items(.tag); + for (file.zir.instructions.items(.data)) |*data, i| { + const as_struct = @ptrCast(*const Stage1DataLayout, data); + safety_buffer[i] = as_struct.data; + } + } + + const header: Zir.Header = .{ + .instructions_len = @intCast(u32, file.zir.instructions.len), + .string_bytes_len = @intCast(u32, file.zir.string_bytes.len), + .extra_len = @intCast(u32, file.zir.extra.len), + + .stat_size = stat.size, + .stat_inode = stat.inode, + .stat_mtime = stat.mtime, + }; + var iovecs = [_]std.os.iovec_const{ + .{ + .iov_base = @ptrCast([*]const u8, &header), + .iov_len = @sizeOf(Zir.Header), + }, + .{ + .iov_base = @ptrCast([*]const u8, file.zir.instructions.items(.tag).ptr), + .iov_len = file.zir.instructions.len, + }, + .{ + .iov_base = data_ptr, + .iov_len = file.zir.instructions.len * 8, + }, + .{ + .iov_base = file.zir.string_bytes.ptr, + .iov_len = file.zir.string_bytes.len, + }, + .{ + .iov_base = @ptrCast([*]const u8, file.zir.extra.ptr), + .iov_len = file.zir.extra.len * 4, + }, + }; + cache_file.?.writevAll(&iovecs) catch |err| { + const pkg_path = file.pkg.root_src_directory.path orelse "."; + const cache_path = cache_directory.path orelse "."; + log.warn("unable to write cached ZIR code for {s}/{s} to {s}/z/{s}: {s}", .{ + pkg_path, file.sub_file_path, cache_path, &digest, @errorName(err), + }); + }; + + // TODO don't report compile errors until Sema @importFile if (file.zir.hasCompileErrors()) { { const lock = comp.mutex.acquire(); @@ -2780,9 +3038,6 @@ pub fn astGenFile(mod: *Module, file: *Scope.File, prog_node: *std.Progress.Node file.status = .astgen_failure; return error.AnalysisFail; } - - log.debug("AstGen success: {s}", .{file.sub_file_path}); - file.status = .success; } pub fn ensureDeclAnalyzed(mod: *Module, decl: *Decl) InnerError!void { diff --git a/src/Zir.zig b/src/Zir.zig index 012643ae9a..7f8f0f2e74 100644 --- a/src/Zir.zig +++ b/src/Zir.zig @@ -37,6 +37,17 @@ string_bytes: []u8, /// The first few indexes are reserved. See `ExtraIndex` for the values. extra: []u32, +/// The data stored at byte offset 0 when ZIR is stored in a file. +pub const Header = extern struct { + instructions_len: u32, + string_bytes_len: u32, + extra_len: u32, + + stat_size: u64, + stat_inode: std.fs.File.INode, + stat_mtime: i128, +}; + pub const ExtraIndex = enum(u32) { /// Ref. The main struct decl for this file. main_struct, @@ -139,6 +150,7 @@ pub const Inst = struct { data: Data, /// These names are used directly as the instruction names in the text format. + /// See `data_field_map` for a list of which `Data` fields are used by each `Tag`. pub const Tag = enum(u8) { /// Arithmetic addition, asserts no integer overflow. /// Uses the `pl_node` union field. Payload is `Bin`. @@ -932,6 +944,7 @@ pub const Inst = struct { /// Uses the `un_node` field. The AST node is the var decl. resolve_inferred_alloc, + /// Implements `resume` syntax. Uses `un_node` field. @"resume", @"await", await_nosuspend, @@ -1202,6 +1215,276 @@ pub const Inst = struct { => true, }; } + + /// Used by debug safety-checking code. + pub const data_tags = list: { + @setEvalBranchQuota(2000); + break :list std.enums.directEnumArray(Tag, Data.FieldEnum, 0, .{ + .add = .pl_node, + .addwrap = .pl_node, + .array_cat = .pl_node, + .array_mul = .pl_node, + .array_type = .bin, + .array_type_sentinel = .array_type_sentinel, + .vector_type = .pl_node, + .elem_type = .un_node, + .indexable_ptr_len = .un_node, + .anyframe_type = .un_node, + .as = .bin, + .as_node = .pl_node, + .bit_and = .pl_node, + .bitcast = .pl_node, + .bitcast_result_ptr = .pl_node, + .bit_not = .un_node, + .bit_or = .pl_node, + .block = .pl_node, + .block_inline = .pl_node, + .block_inline_var = .pl_node, + .suspend_block = .pl_node, + .bool_and = .pl_node, + .bool_not = .un_node, + .bool_or = .pl_node, + .bool_br_and = .bool_br, + .bool_br_or = .bool_br, + .@"break" = .@"break", + .break_inline = .@"break", + .breakpoint = .node, + .call = .pl_node, + .call_chkused = .pl_node, + .call_compile_time = .pl_node, + .call_nosuspend = .pl_node, + .call_async = .pl_node, + .cmp_lt = .pl_node, + .cmp_lte = .pl_node, + .cmp_eq = .pl_node, + .cmp_gte = .pl_node, + .cmp_gt = .pl_node, + .cmp_neq = .pl_node, + .coerce_result_ptr = .bin, + .condbr = .pl_node, + .condbr_inline = .pl_node, + .struct_decl = .pl_node, + .struct_decl_packed = .pl_node, + .struct_decl_extern = .pl_node, + .union_decl = .pl_node, + .union_decl_packed = .pl_node, + .union_decl_extern = .pl_node, + .enum_decl = .pl_node, + .enum_decl_nonexhaustive = .pl_node, + .opaque_decl = .pl_node, + .error_set_decl = .pl_node, + .dbg_stmt_node = .node, + .decl_ref = .str_tok, + .decl_val = .str_tok, + .load = .un_node, + .div = .pl_node, + .elem_ptr = .bin, + .elem_ptr_node = .pl_node, + .elem_val = .bin, + .elem_val_node = .pl_node, + .ensure_result_used = .un_node, + .ensure_result_non_error = .un_node, + .error_union_type = .pl_node, + .error_value = .str_tok, + .@"export" = .pl_node, + .field_ptr = .pl_node, + .field_val = .pl_node, + .field_ptr_named = .pl_node, + .field_val_named = .pl_node, + .func = .pl_node, + .func_inferred = .pl_node, + .import = .str_tok, + .int = .int, + .int_big = .str, + .float = .float, + .float128 = .pl_node, + .int_type = .int_type, + .is_non_null = .un_node, + .is_null = .un_node, + .is_non_null_ptr = .un_node, + .is_null_ptr = .un_node, + .is_err = .un_node, + .is_err_ptr = .un_node, + .loop = .pl_node, + .repeat = .node, + .repeat_inline = .node, + .merge_error_sets = .pl_node, + .mod_rem = .pl_node, + .mul = .pl_node, + .mulwrap = .pl_node, + .param_type = .param_type, + .ref = .un_tok, + .ret_node = .un_node, + .ret_coerce = .un_tok, + .ptr_type_simple = .ptr_type_simple, + .ptr_type = .ptr_type, + .slice_start = .pl_node, + .slice_end = .pl_node, + .slice_sentinel = .pl_node, + .store = .bin, + .store_node = .pl_node, + .store_to_block_ptr = .bin, + .store_to_inferred_ptr = .bin, + .str = .str, + .sub = .pl_node, + .subwrap = .pl_node, + .negate = .un_node, + .negate_wrap = .un_node, + .typeof = .un_tok, + .typeof_elem = .un_node, + .typeof_log2_int_type = .un_node, + .log2_int_type = .un_node, + .@"unreachable" = .@"unreachable", + .xor = .pl_node, + .optional_type = .un_node, + .optional_payload_safe = .un_node, + .optional_payload_unsafe = .un_node, + .optional_payload_safe_ptr = .un_node, + .optional_payload_unsafe_ptr = .un_node, + .err_union_payload_safe = .un_node, + .err_union_payload_unsafe = .un_node, + .err_union_payload_safe_ptr = .un_node, + .err_union_payload_unsafe_ptr = .un_node, + .err_union_code = .un_node, + .err_union_code_ptr = .un_node, + .ensure_err_payload_void = .un_tok, + .enum_literal = .str_tok, + .switch_block = .pl_node, + .switch_block_multi = .pl_node, + .switch_block_else = .pl_node, + .switch_block_else_multi = .pl_node, + .switch_block_under = .pl_node, + .switch_block_under_multi = .pl_node, + .switch_block_ref = .pl_node, + .switch_block_ref_multi = .pl_node, + .switch_block_ref_else = .pl_node, + .switch_block_ref_else_multi = .pl_node, + .switch_block_ref_under = .pl_node, + .switch_block_ref_under_multi = .pl_node, + .switch_capture = .switch_capture, + .switch_capture_ref = .switch_capture, + .switch_capture_multi = .switch_capture, + .switch_capture_multi_ref = .switch_capture, + .switch_capture_else = .switch_capture, + .switch_capture_else_ref = .switch_capture, + .validate_struct_init_ptr = .pl_node, + .validate_array_init_ptr = .pl_node, + .struct_init_empty = .un_node, + .field_type = .pl_node, + .field_type_ref = .pl_node, + .struct_init = .pl_node, + .struct_init_ref = .pl_node, + .struct_init_anon = .pl_node, + .struct_init_anon_ref = .pl_node, + .array_init = .pl_node, + .array_init_anon = .pl_node, + .array_init_ref = .pl_node, + .array_init_anon_ref = .pl_node, + .union_init_ptr = .pl_node, + .type_info = .un_node, + .size_of = .un_node, + .bit_size_of = .un_node, + .fence = .node, + + .ptr_to_int = .un_node, + .error_to_int = .un_node, + .int_to_error = .un_node, + .compile_error = .un_node, + .set_eval_branch_quota = .un_node, + .enum_to_int = .un_node, + .align_of = .un_node, + .bool_to_int = .un_node, + .embed_file = .un_node, + .error_name = .un_node, + .panic = .un_node, + .set_align_stack = .un_node, + .set_cold = .un_node, + .set_float_mode = .un_node, + .set_runtime_safety = .un_node, + .sqrt = .un_node, + .sin = .un_node, + .cos = .un_node, + .exp = .un_node, + .exp2 = .un_node, + .log = .un_node, + .log2 = .un_node, + .log10 = .un_node, + .fabs = .un_node, + .floor = .un_node, + .ceil = .un_node, + .trunc = .un_node, + .round = .un_node, + .tag_name = .un_node, + .reify = .un_node, + .type_name = .un_node, + .frame_type = .un_node, + .frame_size = .un_node, + + .float_to_int = .pl_node, + .int_to_float = .pl_node, + .int_to_ptr = .pl_node, + .int_to_enum = .pl_node, + .float_cast = .pl_node, + .int_cast = .pl_node, + .err_set_cast = .pl_node, + .ptr_cast = .pl_node, + .truncate = .pl_node, + .align_cast = .pl_node, + + .has_decl = .pl_node, + .has_field = .pl_node, + + .clz = .un_node, + .ctz = .un_node, + .pop_count = .un_node, + .byte_swap = .un_node, + .bit_reverse = .un_node, + + .div_exact = .pl_node, + .div_floor = .pl_node, + .div_trunc = .pl_node, + .mod = .pl_node, + .rem = .pl_node, + + .shl = .pl_node, + .shl_exact = .pl_node, + .shr = .pl_node, + .shr_exact = .pl_node, + + .bit_offset_of = .pl_node, + .byte_offset_of = .pl_node, + .cmpxchg_strong = .pl_node, + .cmpxchg_weak = .pl_node, + .splat = .pl_node, + .reduce = .pl_node, + .shuffle = .pl_node, + .atomic_load = .pl_node, + .atomic_rmw = .pl_node, + .atomic_store = .pl_node, + .mul_add = .pl_node, + .builtin_call = .pl_node, + .field_ptr_type = .bin, + .field_parent_ptr = .pl_node, + .memcpy = .pl_node, + .memset = .pl_node, + .builtin_async_call = .pl_node, + .c_import = .pl_node, + + .alloc = .un_node, + .alloc_mut = .un_node, + .alloc_comptime = .un_node, + .alloc_inferred = .node, + .alloc_inferred_mut = .node, + .alloc_inferred_comptime = .node, + .resolve_inferred_alloc = .un_node, + + .@"resume" = .un_node, + .@"await" = .un_node, + .await_nosuspend = .un_node, + + .extended = .extended, + }); + }; }; /// Rarer instructions are here; ones that do not fit in the 8-bit `Tag` enum. @@ -1842,6 +2125,33 @@ pub const Inst = struct { assert(@sizeOf(Data) == 8); } } + + /// TODO this has to be kept in sync with `Data` which we want to be an untagged + /// union. There is some kind of language awkwardness here and it has to do with + /// deserializing an untagged union (in this case `Data`) from a file, and trying + /// to preserve the hidden safety field. + pub const FieldEnum = enum { + extended, + un_node, + un_tok, + pl_node, + bin, + str, + str_tok, + tok, + node, + int, + float, + array_type_sentinel, + ptr_type_simple, + ptr_type, + int_type, + bool_br, + param_type, + @"unreachable", + @"break", + switch_capture, + }; }; /// Trailing: diff --git a/src/main.zig b/src/main.zig index 5e3823abd6..d5a379c8b0 100644 --- a/src/main.zig +++ b/src/main.zig @@ -3606,7 +3606,7 @@ pub fn cmdAstgen( if (file.zir.hasCompileErrors()) { var errors = std.ArrayList(Compilation.AllErrors.Message).init(arena); - try Compilation.AllErrors.addZir(arena, &errors, &file, source); + try Compilation.AllErrors.addZir(arena, &errors, &file); const ttyconf = std.debug.detectTTYConfig(); for (errors.items) |full_err_msg| { full_err_msg.renderToStdErr(ttyconf);