authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-04-25 00:02:58-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-04-25 00:02:58-07:00
log015cd79f89aefd26fb1df91f3d07f7dcade21c4a
tree715e950ffc29e59938152f0691e059863980dd62
parentff2ec0dc5ad272113379ff485bb71c6c1637d948

stage2: implement caching for ZIR code

Notably this exposed an issue with the language having to do with the secret safety tag on untagged unions. How can we have our cake and eat it too? Not solved in this commit. I will file a language proposal to tackle this issue soon. Fixes a compile error in `std.fs.File.readvAll`.

6 files changed, 587 insertions(+), 22 deletions(-)

BRANCH_TODO+3-5
......@@ -1,15 +1,10 @@
1 * nested function decl: how to refer to params?
2 * look for cached zir code
3 * save zir code to cache
41 * keep track of file dependencies/dependants
52 * unload files from memory when a dependency is dropped
6 * implement zir error notes
73
84 * implement the new AstGen compile errors
95
106 * get rid of failed_root_src_file
117 * get rid of Scope.DeclRef
12 * get rid of optional_type_from_ptr_elem
138 * handle decl collision with usingnamespace
149 * the decl doing the looking up needs to create a decl dependency
1510 on each usingnamespace decl
......@@ -38,6 +33,9 @@
3833 AstGen can report more than one compile error.
3934
4035 * AstGen: add result location pointers to function calls
36 * nested function decl: how to refer to params?
37
38 * detect when to put cached ZIR into the local cache instead of the global one
4139
4240 const container_name_hash: Scope.NameHash = if (found_pkg) |pkg|
4341 pkg.namespace_hash
lib/std/fs/file.zig+1-1
......@@ -482,7 +482,7 @@ pub const File = struct {
482482 /// order to handle partial reads from the underlying OS layer.
483483 /// See https://github.com/ziglang/zig/issues/7699
484484 pub fn readvAll(self: File, iovecs: []os.iovec) ReadError!usize {
485 if (iovecs.len == 0) return;
485 if (iovecs.len == 0) return 0;
486486
487487 var i: usize = 0;
488488 var off: usize = 0;
src/Compilation.zig+8-6
......@@ -434,10 +434,10 @@ pub const AllErrors = struct {
434434 arena: *Allocator,
435435 errors: *std.ArrayList(Message),
436436 file: *Module.Scope.File,
437 source: []const u8,
438437 ) !void {
439438 assert(file.zir_loaded);
440439 assert(file.tree_loaded);
440 assert(file.source_loaded);
441441 const payload_index = file.zir.extra[@enumToInt(Zir.ExtraIndex.compile_errors)];
442442 assert(payload_index != 0);
443443
......@@ -466,7 +466,7 @@ pub const AllErrors = struct {
466466 }
467467 break :blk token_starts[note_item.data.token] + note_item.data.byte_offset;
468468 };
469 const loc = std.zig.findLineColumn(source, byte_offset);
469 const loc = std.zig.findLineColumn(file.source, byte_offset);
470470
471471 note.* = .{
472472 .src = .{
......@@ -492,7 +492,7 @@ pub const AllErrors = struct {
492492 }
493493 break :blk token_starts[item.data.token] + item.data.byte_offset;
494494 };
495 const loc = std.zig.findLineColumn(source, byte_offset);
495 const loc = std.zig.findLineColumn(file.source, byte_offset);
496496
497497 try errors.append(.{
498498 .src = .{
......@@ -1709,9 +1709,11 @@ pub fn getAllErrorsAlloc(self: *Compilation) !AllErrors {
17091709 if (entry.value) |msg| {
17101710 try AllErrors.add(module, &arena, &errors, msg.*);
17111711 } else {
1712 // Must be ZIR errors.
1713 const source = try entry.key.getSource(module.gpa);
1714 try AllErrors.addZir(&arena.allocator, &errors, entry.key, source);
1712 // Must be ZIR errors. In order for ZIR errors to exist, the parsing
1713 // must have completed successfully.
1714 const tree = try entry.key.getTree(module.gpa);
1715 assert(tree.errors.len == 0);
1716 try AllErrors.addZir(&arena.allocator, &errors, entry.key);
17151717 }
17161718 }
17171719 for (module.failed_decls.items()) |entry| {
src/Module.zig+264-9
......@@ -15,6 +15,7 @@ const ast = std.zig.ast;
1515
1616const Module = @This();
1717const Compilation = @import("Compilation.zig");
18const Cache = @import("Cache.zig");
1819const Value = @import("value.zig").Value;
1920const Type = @import("type.zig").Type;
2021const TypedValue = @import("TypedValue.zig");
......@@ -771,6 +772,15 @@ pub const Scope = struct {
771772 return source;
772773 }
773774
775 pub fn getTree(file: *File, gpa: *Allocator) !*const ast.Tree {
776 if (file.tree_loaded) return &file.tree;
777
778 const source = try file.getSource(gpa);
779 file.tree = try std.zig.parse(gpa, source);
780 file.tree_loaded = true;
781 return &file.tree;
782 }
783
774784 pub fn destroy(file: *File, gpa: *Allocator) void {
775785 file.deinit(gpa);
776786 gpa.destroy(file);
......@@ -2676,6 +2686,20 @@ fn freeExportList(gpa: *Allocator, export_list: []*Export) void {
26762686 gpa.free(export_list);
26772687}
26782688
2689const data_has_safety_tag = @sizeOf(Zir.Inst.Data) != 8;
2690// TODO This is taking advantage of matching stage1 debug union layout.
2691// We need a better language feature for initializing a union with
2692// a runtime known tag.
2693const Stage1DataLayout = extern struct {
2694 safety_tag: u8,
2695 data: [8]u8 align(8),
2696};
2697comptime {
2698 if (data_has_safety_tag) {
2699 assert(@sizeOf(Stage1DataLayout) == @sizeOf(Zir.Inst.Data));
2700 }
2701}
2702
26792703pub fn astGenFile(mod: *Module, file: *Scope.File, prog_node: *std.Progress.Node) !void {
26802704 const tracy = trace(@src());
26812705 defer tracy.end();
......@@ -2684,15 +2708,166 @@ pub fn astGenFile(mod: *Module, file: *Scope.File, prog_node: *std.Progress.Node
26842708 const gpa = mod.gpa;
26852709
26862710 // In any case we need to examine the stat of the file to determine the course of action.
2687 var f = try file.pkg.root_src_directory.handle.openFile(file.sub_file_path, .{});
2688 defer f.close();
2711 var source_file = try file.pkg.root_src_directory.handle.openFile(file.sub_file_path, .{});
2712 defer source_file.close();
26892713
2690 const stat = try f.stat();
2714 const stat = try source_file.stat();
2715
2716 const want_local_cache = file.pkg == mod.root_pkg;
2717 const digest = hash: {
2718 var path_hash: Cache.HashHelper = .{};
2719 if (!want_local_cache) {
2720 path_hash.addOptionalBytes(file.pkg.root_src_directory.path);
2721 }
2722 path_hash.addBytes(file.sub_file_path);
2723 break :hash path_hash.final();
2724 };
2725 const cache_directory = if (want_local_cache)
2726 comp.local_cache_directory
2727 else
2728 comp.global_cache_directory;
2729
2730 var cache_file: ?std.fs.File = null;
2731 defer if (cache_file) |f| f.close();
2732
2733 // TODO do this before spawning astgen workers
2734 var zir_dir = try cache_directory.handle.makeOpenPath("z", .{});
2735 defer zir_dir.close();
26912736
26922737 // Determine whether we need to reload the file from disk and redo parsing and AstGen.
26932738 switch (file.status) {
2694 .never_loaded, .retryable_failure => {
2695 log.debug("first-time AstGen: {s}", .{file.sub_file_path});
2739 .never_loaded, .retryable_failure => cached: {
2740 // First, load the cached ZIR code, if any.
2741 log.debug("AstGen checking cache: {s} (local={}, digest={s})", .{
2742 file.sub_file_path, want_local_cache, &digest,
2743 });
2744
2745 // We ask for a lock in order to coordinate with other zig processes.
2746 // If another process is already working on this file, we will get the cached
2747 // version. Likewise if we're working on AstGen and another process asks for
2748 // the cached file, they'll get it.
2749 cache_file = zir_dir.openFile(&digest, .{ .lock = .Shared }) catch |err| switch (err) {
2750 error.PathAlreadyExists => unreachable, // opening for reading
2751 error.NoSpaceLeft => unreachable, // opening for reading
2752 error.NotDir => unreachable, // no dir components
2753 error.InvalidUtf8 => unreachable, // it's a hex encoded name
2754 error.BadPathName => unreachable, // it's a hex encoded name
2755 error.NameTooLong => unreachable, // it's a fixed size name
2756 error.PipeBusy => unreachable, // it's not a pipe
2757 error.WouldBlock => unreachable, // not asking for non-blocking I/O
2758
2759 error.SymLinkLoop,
2760 error.FileNotFound,
2761 error.Unexpected,
2762 => break :cached,
2763
2764 else => |e| return e, // Retryable errors are handled at callsite.
2765 };
2766
2767 // First we read the header to determine the lengths of arrays.
2768 const header = cache_file.?.reader().readStruct(Zir.Header) catch |err| switch (err) {
2769 // This can happen if Zig bails out of this function between creating
2770 // the cached file and writing it.
2771 error.EndOfStream => break :cached,
2772 else => |e| return e,
2773 };
2774 const unchanged_metadata =
2775 stat.size == header.stat_size and
2776 stat.mtime == header.stat_mtime and
2777 stat.inode == header.stat_inode;
2778
2779 if (!unchanged_metadata) {
2780 log.debug("AstGen cache stale: {s}", .{file.sub_file_path});
2781 break :cached;
2782 }
2783 log.debug("AstGen cache hit: {s}", .{file.sub_file_path});
2784
2785 var instructions: std.MultiArrayList(Zir.Inst) = .{};
2786 defer instructions.deinit(gpa);
2787
2788 try instructions.resize(gpa, header.instructions_len);
2789
2790 var zir: Zir = .{
2791 .instructions = instructions.toOwnedSlice(),
2792 .string_bytes = &.{},
2793 .extra = &.{},
2794 };
2795 var keep_zir = false;
2796 defer if (!keep_zir) zir.deinit(gpa);
2797
2798 zir.string_bytes = try gpa.alloc(u8, header.string_bytes_len);
2799 zir.extra = try gpa.alloc(u32, header.extra_len);
2800
2801 const safety_buffer = if (data_has_safety_tag)
2802 try gpa.alloc([8]u8, header.instructions_len)
2803 else
2804 undefined;
2805 defer if (data_has_safety_tag) gpa.free(safety_buffer);
2806
2807 const data_ptr = if (data_has_safety_tag)
2808 @ptrCast([*]u8, safety_buffer.ptr)
2809 else
2810 @ptrCast([*]u8, zir.instructions.items(.data).ptr);
2811
2812 var iovecs = [_]std.os.iovec{
2813 .{
2814 .iov_base = @ptrCast([*]u8, zir.instructions.items(.tag).ptr),
2815 .iov_len = header.instructions_len,
2816 },
2817 .{
2818 .iov_base = data_ptr,
2819 .iov_len = header.instructions_len * 8,
2820 },
2821 .{
2822 .iov_base = zir.string_bytes.ptr,
2823 .iov_len = header.string_bytes_len,
2824 },
2825 .{
2826 .iov_base = @ptrCast([*]u8, zir.extra.ptr),
2827 .iov_len = header.extra_len * 4,
2828 },
2829 };
2830 const amt_read = try cache_file.?.readvAll(&iovecs);
2831 const amt_expected = zir.instructions.len * 9 +
2832 zir.string_bytes.len +
2833 zir.extra.len * 4;
2834 if (amt_read != amt_expected) {
2835 log.warn("unexpected EOF reading cached ZIR for {s}", .{file.sub_file_path});
2836 zir.deinit(gpa);
2837 break :cached;
2838 }
2839 if (data_has_safety_tag) {
2840 const tags = zir.instructions.items(.tag);
2841 for (zir.instructions.items(.data)) |*data, i| {
2842 const union_tag = Zir.Inst.Tag.data_tags[@enumToInt(tags[i])];
2843 const as_struct = @ptrCast(*Stage1DataLayout, data);
2844 as_struct.* = .{
2845 .safety_tag = @enumToInt(union_tag),
2846 .data = safety_buffer[i],
2847 };
2848 }
2849 }
2850
2851 keep_zir = true;
2852 file.zir = zir;
2853 file.zir_loaded = true;
2854 file.stat_size = header.stat_size;
2855 file.stat_inode = header.stat_inode;
2856 file.stat_mtime = header.stat_mtime;
2857 file.status = .success;
2858 log.debug("AstGen cached success: {s}", .{file.sub_file_path});
2859
2860 // TODO don't report compile errors until Sema @importFile
2861 if (file.zir.hasCompileErrors()) {
2862 {
2863 const lock = comp.mutex.acquire();
2864 defer lock.release();
2865 try mod.failed_files.putNoClobber(gpa, file, null);
2866 }
2867 file.status = .astgen_failure;
2868 return error.AnalysisFail;
2869 }
2870 return;
26962871 },
26972872 .parse_failure, .astgen_failure, .success => {
26982873 const unchanged_metadata =
......@@ -2708,6 +2883,29 @@ pub fn astGenFile(mod: *Module, file: *Scope.File, prog_node: *std.Progress.Node
27082883 log.debug("metadata changed: {s}", .{file.sub_file_path});
27092884 },
27102885 }
2886 if (cache_file) |f| {
2887 f.close();
2888 cache_file = null;
2889 }
2890 cache_file = zir_dir.createFile(&digest, .{ .lock = .Exclusive }) catch |err| switch (err) {
2891 error.NotDir => unreachable, // no dir components
2892 error.InvalidUtf8 => unreachable, // it's a hex encoded name
2893 error.BadPathName => unreachable, // it's a hex encoded name
2894 error.NameTooLong => unreachable, // it's a fixed size name
2895 error.PipeBusy => unreachable, // it's not a pipe
2896 error.WouldBlock => unreachable, // not asking for non-blocking I/O
2897 error.FileNotFound => unreachable, // no dir components
2898
2899 else => |e| {
2900 const pkg_path = file.pkg.root_src_directory.path orelse ".";
2901 const cache_path = cache_directory.path orelse ".";
2902 log.warn("unable to save cached ZIR code for {s}/{s} to {s}/z/{s}: {s}", .{
2903 pkg_path, file.sub_file_path, cache_path, &digest, @errorName(e),
2904 });
2905 return;
2906 },
2907 };
2908
27112909 // Clear compile error for this file.
27122910 switch (file.status) {
27132911 .success, .retryable_failure => {},
......@@ -2726,7 +2924,7 @@ pub fn astGenFile(mod: *Module, file: *Scope.File, prog_node: *std.Progress.Node
27262924
27272925 const source = try gpa.allocSentinel(u8, stat.size, 0);
27282926 defer if (!file.source_loaded) gpa.free(source);
2729 const amt = try f.readAll(source);
2927 const amt = try source_file.readAll(source);
27302928 if (amt != stat.size)
27312929 return error.UnexpectedEndOfFile;
27322930
......@@ -2770,7 +2968,67 @@ pub fn astGenFile(mod: *Module, file: *Scope.File, prog_node: *std.Progress.Node
27702968
27712969 file.zir = try AstGen.generate(gpa, file);
27722970 file.zir_loaded = true;
2971 file.status = .success;
2972 log.debug("AstGen fresh success: {s}", .{file.sub_file_path});
2973
2974 const safety_buffer = if (data_has_safety_tag)
2975 try gpa.alloc([8]u8, file.zir.instructions.len)
2976 else
2977 undefined;
2978 defer if (data_has_safety_tag) gpa.free(safety_buffer);
2979 const data_ptr = if (data_has_safety_tag)
2980 @ptrCast([*]const u8, safety_buffer.ptr)
2981 else
2982 @ptrCast([*]const u8, file.zir.instructions.items(.data).ptr);
2983 if (data_has_safety_tag) {
2984 // The `Data` union has a safety tag but in the file format we store it without.
2985 const tags = file.zir.instructions.items(.tag);
2986 for (file.zir.instructions.items(.data)) |*data, i| {
2987 const as_struct = @ptrCast(*const Stage1DataLayout, data);
2988 safety_buffer[i] = as_struct.data;
2989 }
2990 }
2991
2992 const header: Zir.Header = .{
2993 .instructions_len = @intCast(u32, file.zir.instructions.len),
2994 .string_bytes_len = @intCast(u32, file.zir.string_bytes.len),
2995 .extra_len = @intCast(u32, file.zir.extra.len),
2996
2997 .stat_size = stat.size,
2998 .stat_inode = stat.inode,
2999 .stat_mtime = stat.mtime,
3000 };
3001 var iovecs = [_]std.os.iovec_const{
3002 .{
3003 .iov_base = @ptrCast([*]const u8, &header),
3004 .iov_len = @sizeOf(Zir.Header),
3005 },
3006 .{
3007 .iov_base = @ptrCast([*]const u8, file.zir.instructions.items(.tag).ptr),
3008 .iov_len = file.zir.instructions.len,
3009 },
3010 .{
3011 .iov_base = data_ptr,
3012 .iov_len = file.zir.instructions.len * 8,
3013 },
3014 .{
3015 .iov_base = file.zir.string_bytes.ptr,
3016 .iov_len = file.zir.string_bytes.len,
3017 },
3018 .{
3019 .iov_base = @ptrCast([*]const u8, file.zir.extra.ptr),
3020 .iov_len = file.zir.extra.len * 4,
3021 },
3022 };
3023 cache_file.?.writevAll(&iovecs) catch |err| {
3024 const pkg_path = file.pkg.root_src_directory.path orelse ".";
3025 const cache_path = cache_directory.path orelse ".";
3026 log.warn("unable to write cached ZIR code for {s}/{s} to {s}/z/{s}: {s}", .{
3027 pkg_path, file.sub_file_path, cache_path, &digest, @errorName(err),
3028 });
3029 };
27733030
3031 // TODO don't report compile errors until Sema @importFile
27743032 if (file.zir.hasCompileErrors()) {
27753033 {
27763034 const lock = comp.mutex.acquire();
......@@ -2780,9 +3038,6 @@ pub fn astGenFile(mod: *Module, file: *Scope.File, prog_node: *std.Progress.Node
27803038 file.status = .astgen_failure;
27813039 return error.AnalysisFail;
27823040 }
2783
2784 log.debug("AstGen success: {s}", .{file.sub_file_path});
2785 file.status = .success;
27863041}
27873042
27883043pub fn ensureDeclAnalyzed(mod: *Module, decl: *Decl) InnerError!void {
src/Zir.zig+310
......@@ -37,6 +37,17 @@ string_bytes: []u8,
3737/// The first few indexes are reserved. See `ExtraIndex` for the values.
3838extra: []u32,
3939
40/// The data stored at byte offset 0 when ZIR is stored in a file.
41pub const Header = extern struct {
42 instructions_len: u32,
43 string_bytes_len: u32,
44 extra_len: u32,
45
46 stat_size: u64,
47 stat_inode: std.fs.File.INode,
48 stat_mtime: i128,
49};
50
4051pub const ExtraIndex = enum(u32) {
4152 /// Ref. The main struct decl for this file.
4253 main_struct,
......@@ -139,6 +150,7 @@ pub const Inst = struct {
139150 data: Data,
140151
141152 /// These names are used directly as the instruction names in the text format.
153 /// See `data_field_map` for a list of which `Data` fields are used by each `Tag`.
142154 pub const Tag = enum(u8) {
143155 /// Arithmetic addition, asserts no integer overflow.
144156 /// Uses the `pl_node` union field. Payload is `Bin`.
......@@ -932,6 +944,7 @@ pub const Inst = struct {
932944 /// Uses the `un_node` field. The AST node is the var decl.
933945 resolve_inferred_alloc,
934946
947 /// Implements `resume` syntax. Uses `un_node` field.
935948 @"resume",
936949 @"await",
937950 await_nosuspend,
......@@ -1202,6 +1215,276 @@ pub const Inst = struct {
12021215 => true,
12031216 };
12041217 }
1218
1219 /// Used by debug safety-checking code.
1220 pub const data_tags = list: {
1221 @setEvalBranchQuota(2000);
1222 break :list std.enums.directEnumArray(Tag, Data.FieldEnum, 0, .{
1223 .add = .pl_node,
1224 .addwrap = .pl_node,
1225 .array_cat = .pl_node,
1226 .array_mul = .pl_node,
1227 .array_type = .bin,
1228 .array_type_sentinel = .array_type_sentinel,
1229 .vector_type = .pl_node,
1230 .elem_type = .un_node,
1231 .indexable_ptr_len = .un_node,
1232 .anyframe_type = .un_node,
1233 .as = .bin,
1234 .as_node = .pl_node,
1235 .bit_and = .pl_node,
1236 .bitcast = .pl_node,
1237 .bitcast_result_ptr = .pl_node,
1238 .bit_not = .un_node,
1239 .bit_or = .pl_node,
1240 .block = .pl_node,
1241 .block_inline = .pl_node,
1242 .block_inline_var = .pl_node,
1243 .suspend_block = .pl_node,
1244 .bool_and = .pl_node,
1245 .bool_not = .un_node,
1246 .bool_or = .pl_node,
1247 .bool_br_and = .bool_br,
1248 .bool_br_or = .bool_br,
1249 .@"break" = .@"break",
1250 .break_inline = .@"break",
1251 .breakpoint = .node,
1252 .call = .pl_node,
1253 .call_chkused = .pl_node,
1254 .call_compile_time = .pl_node,
1255 .call_nosuspend = .pl_node,
1256 .call_async = .pl_node,
1257 .cmp_lt = .pl_node,
1258 .cmp_lte = .pl_node,
1259 .cmp_eq = .pl_node,
1260 .cmp_gte = .pl_node,
1261 .cmp_gt = .pl_node,
1262 .cmp_neq = .pl_node,
1263 .coerce_result_ptr = .bin,
1264 .condbr = .pl_node,
1265 .condbr_inline = .pl_node,
1266 .struct_decl = .pl_node,
1267 .struct_decl_packed = .pl_node,
1268 .struct_decl_extern = .pl_node,
1269 .union_decl = .pl_node,
1270 .union_decl_packed = .pl_node,
1271 .union_decl_extern = .pl_node,
1272 .enum_decl = .pl_node,
1273 .enum_decl_nonexhaustive = .pl_node,
1274 .opaque_decl = .pl_node,
1275 .error_set_decl = .pl_node,
1276 .dbg_stmt_node = .node,
1277 .decl_ref = .str_tok,
1278 .decl_val = .str_tok,
1279 .load = .un_node,
1280 .div = .pl_node,
1281 .elem_ptr = .bin,
1282 .elem_ptr_node = .pl_node,
1283 .elem_val = .bin,
1284 .elem_val_node = .pl_node,
1285 .ensure_result_used = .un_node,
1286 .ensure_result_non_error = .un_node,
1287 .error_union_type = .pl_node,
1288 .error_value = .str_tok,
1289 .@"export" = .pl_node,
1290 .field_ptr = .pl_node,
1291 .field_val = .pl_node,
1292 .field_ptr_named = .pl_node,
1293 .field_val_named = .pl_node,
1294 .func = .pl_node,
1295 .func_inferred = .pl_node,
1296 .import = .str_tok,
1297 .int = .int,
1298 .int_big = .str,
1299 .float = .float,
1300 .float128 = .pl_node,
1301 .int_type = .int_type,
1302 .is_non_null = .un_node,
1303 .is_null = .un_node,
1304 .is_non_null_ptr = .un_node,
1305 .is_null_ptr = .un_node,
1306 .is_err = .un_node,
1307 .is_err_ptr = .un_node,
1308 .loop = .pl_node,
1309 .repeat = .node,
1310 .repeat_inline = .node,
1311 .merge_error_sets = .pl_node,
1312 .mod_rem = .pl_node,
1313 .mul = .pl_node,
1314 .mulwrap = .pl_node,
1315 .param_type = .param_type,
1316 .ref = .un_tok,
1317 .ret_node = .un_node,
1318 .ret_coerce = .un_tok,
1319 .ptr_type_simple = .ptr_type_simple,
1320 .ptr_type = .ptr_type,
1321 .slice_start = .pl_node,
1322 .slice_end = .pl_node,
1323 .slice_sentinel = .pl_node,
1324 .store = .bin,
1325 .store_node = .pl_node,
1326 .store_to_block_ptr = .bin,
1327 .store_to_inferred_ptr = .bin,
1328 .str = .str,
1329 .sub = .pl_node,
1330 .subwrap = .pl_node,
1331 .negate = .un_node,
1332 .negate_wrap = .un_node,
1333 .typeof = .un_tok,
1334 .typeof_elem = .un_node,
1335 .typeof_log2_int_type = .un_node,
1336 .log2_int_type = .un_node,
1337 .@"unreachable" = .@"unreachable",
1338 .xor = .pl_node,
1339 .optional_type = .un_node,
1340 .optional_payload_safe = .un_node,
1341 .optional_payload_unsafe = .un_node,
1342 .optional_payload_safe_ptr = .un_node,
1343 .optional_payload_unsafe_ptr = .un_node,
1344 .err_union_payload_safe = .un_node,
1345 .err_union_payload_unsafe = .un_node,
1346 .err_union_payload_safe_ptr = .un_node,
1347 .err_union_payload_unsafe_ptr = .un_node,
1348 .err_union_code = .un_node,
1349 .err_union_code_ptr = .un_node,
1350 .ensure_err_payload_void = .un_tok,
1351 .enum_literal = .str_tok,
1352 .switch_block = .pl_node,
1353 .switch_block_multi = .pl_node,
1354 .switch_block_else = .pl_node,
1355 .switch_block_else_multi = .pl_node,
1356 .switch_block_under = .pl_node,
1357 .switch_block_under_multi = .pl_node,
1358 .switch_block_ref = .pl_node,
1359 .switch_block_ref_multi = .pl_node,
1360 .switch_block_ref_else = .pl_node,
1361 .switch_block_ref_else_multi = .pl_node,
1362 .switch_block_ref_under = .pl_node,
1363 .switch_block_ref_under_multi = .pl_node,
1364 .switch_capture = .switch_capture,
1365 .switch_capture_ref = .switch_capture,
1366 .switch_capture_multi = .switch_capture,
1367 .switch_capture_multi_ref = .switch_capture,
1368 .switch_capture_else = .switch_capture,
1369 .switch_capture_else_ref = .switch_capture,
1370 .validate_struct_init_ptr = .pl_node,
1371 .validate_array_init_ptr = .pl_node,
1372 .struct_init_empty = .un_node,
1373 .field_type = .pl_node,
1374 .field_type_ref = .pl_node,
1375 .struct_init = .pl_node,
1376 .struct_init_ref = .pl_node,
1377 .struct_init_anon = .pl_node,
1378 .struct_init_anon_ref = .pl_node,
1379 .array_init = .pl_node,
1380 .array_init_anon = .pl_node,
1381 .array_init_ref = .pl_node,
1382 .array_init_anon_ref = .pl_node,
1383 .union_init_ptr = .pl_node,
1384 .type_info = .un_node,
1385 .size_of = .un_node,
1386 .bit_size_of = .un_node,
1387 .fence = .node,
1388
1389 .ptr_to_int = .un_node,
1390 .error_to_int = .un_node,
1391 .int_to_error = .un_node,
1392 .compile_error = .un_node,
1393 .set_eval_branch_quota = .un_node,
1394 .enum_to_int = .un_node,
1395 .align_of = .un_node,
1396 .bool_to_int = .un_node,
1397 .embed_file = .un_node,
1398 .error_name = .un_node,
1399 .panic = .un_node,
1400 .set_align_stack = .un_node,
1401 .set_cold = .un_node,
1402 .set_float_mode = .un_node,
1403 .set_runtime_safety = .un_node,
1404 .sqrt = .un_node,
1405 .sin = .un_node,
1406 .cos = .un_node,
1407 .exp = .un_node,
1408 .exp2 = .un_node,
1409 .log = .un_node,
1410 .log2 = .un_node,
1411 .log10 = .un_node,
1412 .fabs = .un_node,
1413 .floor = .un_node,
1414 .ceil = .un_node,
1415 .trunc = .un_node,
1416 .round = .un_node,
1417 .tag_name = .un_node,
1418 .reify = .un_node,
1419 .type_name = .un_node,
1420 .frame_type = .un_node,
1421 .frame_size = .un_node,
1422
1423 .float_to_int = .pl_node,
1424 .int_to_float = .pl_node,
1425 .int_to_ptr = .pl_node,
1426 .int_to_enum = .pl_node,
1427 .float_cast = .pl_node,
1428 .int_cast = .pl_node,
1429 .err_set_cast = .pl_node,
1430 .ptr_cast = .pl_node,
1431 .truncate = .pl_node,
1432 .align_cast = .pl_node,
1433
1434 .has_decl = .pl_node,
1435 .has_field = .pl_node,
1436
1437 .clz = .un_node,
1438 .ctz = .un_node,
1439 .pop_count = .un_node,
1440 .byte_swap = .un_node,
1441 .bit_reverse = .un_node,
1442
1443 .div_exact = .pl_node,
1444 .div_floor = .pl_node,
1445 .div_trunc = .pl_node,
1446 .mod = .pl_node,
1447 .rem = .pl_node,
1448
1449 .shl = .pl_node,
1450 .shl_exact = .pl_node,
1451 .shr = .pl_node,
1452 .shr_exact = .pl_node,
1453
1454 .bit_offset_of = .pl_node,
1455 .byte_offset_of = .pl_node,
1456 .cmpxchg_strong = .pl_node,
1457 .cmpxchg_weak = .pl_node,
1458 .splat = .pl_node,
1459 .reduce = .pl_node,
1460 .shuffle = .pl_node,
1461 .atomic_load = .pl_node,
1462 .atomic_rmw = .pl_node,
1463 .atomic_store = .pl_node,
1464 .mul_add = .pl_node,
1465 .builtin_call = .pl_node,
1466 .field_ptr_type = .bin,
1467 .field_parent_ptr = .pl_node,
1468 .memcpy = .pl_node,
1469 .memset = .pl_node,
1470 .builtin_async_call = .pl_node,
1471 .c_import = .pl_node,
1472
1473 .alloc = .un_node,
1474 .alloc_mut = .un_node,
1475 .alloc_comptime = .un_node,
1476 .alloc_inferred = .node,
1477 .alloc_inferred_mut = .node,
1478 .alloc_inferred_comptime = .node,
1479 .resolve_inferred_alloc = .un_node,
1480
1481 .@"resume" = .un_node,
1482 .@"await" = .un_node,
1483 .await_nosuspend = .un_node,
1484
1485 .extended = .extended,
1486 });
1487 };
12051488 };
12061489
12071490 /// Rarer instructions are here; ones that do not fit in the 8-bit `Tag` enum.
......@@ -1842,6 +2125,33 @@ pub const Inst = struct {
18422125 assert(@sizeOf(Data) == 8);
18432126 }
18442127 }
2128
2129 /// TODO this has to be kept in sync with `Data` which we want to be an untagged
2130 /// union. There is some kind of language awkwardness here and it has to do with
2131 /// deserializing an untagged union (in this case `Data`) from a file, and trying
2132 /// to preserve the hidden safety field.
2133 pub const FieldEnum = enum {
2134 extended,
2135 un_node,
2136 un_tok,
2137 pl_node,
2138 bin,
2139 str,
2140 str_tok,
2141 tok,
2142 node,
2143 int,
2144 float,
2145 array_type_sentinel,
2146 ptr_type_simple,
2147 ptr_type,
2148 int_type,
2149 bool_br,
2150 param_type,
2151 @"unreachable",
2152 @"break",
2153 switch_capture,
2154 };
18452155 };
18462156
18472157 /// Trailing:
src/main.zig+1-1
......@@ -3606,7 +3606,7 @@ pub fn cmdAstgen(
36063606
36073607 if (file.zir.hasCompileErrors()) {
36083608 var errors = std.ArrayList(Compilation.AllErrors.Message).init(arena);
3609 try Compilation.AllErrors.addZir(arena, &errors, &file, source);
3609 try Compilation.AllErrors.addZir(arena, &errors, &file);
36103610 const ttyconf = std.debug.detectTTYConfig();
36113611 for (errors.items) |full_err_msg| {
36123612 full_err_msg.renderToStdErr(ttyconf);