| author | |
| committer | |
| log | 0c8072506883db21d5f8e3e7e7cb45b36d496f28 |
| tree | 2bdfd1254c7931322ea75ffb2c5823000c5083d0 |
| parent | 648b492ef1d962cabd7d2f017ef47aef73c0c3aa |
| parent | 0784d389844a127248bb724352ce7101bc49784c |
| signature |
Begin re-implementing incremental compilation11 files changed, 1308 insertions(+), 300 deletions(-)
lib/std/zig.zig+3-2| ... | @@ -27,11 +27,12 @@ pub const parseNumberLiteral = number_literal.parseNumberLiteral; | ... | @@ -27,11 +27,12 @@ pub const parseNumberLiteral = number_literal.parseNumberLiteral; |
| 27 | pub const c_builtins = @import("zig/c_builtins.zig"); | 27 | pub const c_builtins = @import("zig/c_builtins.zig"); |
| 28 | pub const c_translation = @import("zig/c_translation.zig"); | 28 | pub const c_translation = @import("zig/c_translation.zig"); |
| 29 | 29 | ||
| 30 | pub const SrcHasher = std.crypto.hash.Blake3; | ||
| 30 | pub const SrcHash = [16]u8; | 31 | pub const SrcHash = [16]u8; |
| 31 | 32 | ||
| 32 | pub fn hashSrc(src: []const u8) SrcHash { | 33 | pub fn hashSrc(src: []const u8) SrcHash { |
| 33 | var out: SrcHash = undefined; | 34 | var out: SrcHash = undefined; |
| 34 | std.crypto.hash.Blake3.hash(src, &out, .{}); | 35 | SrcHasher.hash(src, &out, .{}); |
| 35 | return out; | 36 | return out; |
| 36 | } | 37 | } |
| 37 | 38 | ||
| ... | @@ -41,7 +42,7 @@ pub fn srcHashEql(a: SrcHash, b: SrcHash) bool { | ... | @@ -41,7 +42,7 @@ pub fn srcHashEql(a: SrcHash, b: SrcHash) bool { |
| 41 | 42 | ||
| 42 | pub fn hashName(parent_hash: SrcHash, sep: []const u8, name: []const u8) SrcHash { | 43 | pub fn hashName(parent_hash: SrcHash, sep: []const u8, name: []const u8) SrcHash { |
| 43 | var out: SrcHash = undefined; | 44 | var out: SrcHash = undefined; |
| 44 | var hasher = std.crypto.hash.Blake3.init(.{}); | 45 | var hasher = SrcHasher.init(.{}); |
| 45 | hasher.update(&parent_hash); | 46 | hasher.update(&parent_hash); |
| 46 | hasher.update(sep); | 47 | hasher.update(sep); |
| 47 | hasher.update(name); | 48 | hasher.update(name); |
src/AstGen.zig+93-16| ... | @@ -4815,6 +4815,7 @@ fn structDeclInner( | ... | @@ -4815,6 +4815,7 @@ fn structDeclInner( |
| 4815 | .any_comptime_fields = false, | 4815 | .any_comptime_fields = false, |
| 4816 | .any_default_inits = false, | 4816 | .any_default_inits = false, |
| 4817 | .any_aligned_fields = false, | 4817 | .any_aligned_fields = false, |
| 4818 | .fields_hash = std.zig.hashSrc(@tagName(layout)), | ||
| 4818 | }); | 4819 | }); |
| 4819 | return decl_inst.toRef(); | 4820 | return decl_inst.toRef(); |
| 4820 | } | 4821 | } |
| ... | @@ -4936,6 +4937,12 @@ fn structDeclInner( | ... | @@ -4936,6 +4937,12 @@ fn structDeclInner( |
| 4936 | } | 4937 | } |
| 4937 | }; | 4938 | }; |
| 4938 | 4939 | ||
| 4940 | var fields_hasher = std.zig.SrcHasher.init(.{}); | ||
| 4941 | fields_hasher.update(@tagName(layout)); | ||
| 4942 | if (backing_int_node != 0) { | ||
| 4943 | fields_hasher.update(tree.getNodeSource(backing_int_node)); | ||
| 4944 | } | ||
| 4945 | |||
| 4939 | var sfba = std.heap.stackFallback(256, astgen.arena); | 4946 | var sfba = std.heap.stackFallback(256, astgen.arena); |
| 4940 | const sfba_allocator = sfba.get(); | 4947 | const sfba_allocator = sfba.get(); |
| 4941 | 4948 | ||
| ... | @@ -4956,6 +4963,8 @@ fn structDeclInner( | ... | @@ -4956,6 +4963,8 @@ fn structDeclInner( |
| 4956 | .field => |field| field, | 4963 | .field => |field| field, |
| 4957 | }; | 4964 | }; |
| 4958 | 4965 | ||
| 4966 | fields_hasher.update(tree.getNodeSource(member_node)); | ||
| 4967 | |||
| 4959 | if (!is_tuple) { | 4968 | if (!is_tuple) { |
| 4960 | const field_name = try astgen.identAsString(member.ast.main_token); | 4969 | const field_name = try astgen.identAsString(member.ast.main_token); |
| 4961 | 4970 | ||
| ... | @@ -5083,6 +5092,9 @@ fn structDeclInner( | ... | @@ -5083,6 +5092,9 @@ fn structDeclInner( |
| 5083 | return error.AnalysisFail; | 5092 | return error.AnalysisFail; |
| 5084 | } | 5093 | } |
| 5085 | 5094 | ||
| 5095 | var fields_hash: std.zig.SrcHash = undefined; | ||
| 5096 | fields_hasher.final(&fields_hash); | ||
| 5097 | |||
| 5086 | try gz.setStruct(decl_inst, .{ | 5098 | try gz.setStruct(decl_inst, .{ |
| 5087 | .src_node = node, | 5099 | .src_node = node, |
| 5088 | .layout = layout, | 5100 | .layout = layout, |
| ... | @@ -5096,6 +5108,7 @@ fn structDeclInner( | ... | @@ -5096,6 +5108,7 @@ fn structDeclInner( |
| 5096 | .any_comptime_fields = any_comptime_fields, | 5108 | .any_comptime_fields = any_comptime_fields, |
| 5097 | .any_default_inits = any_default_inits, | 5109 | .any_default_inits = any_default_inits, |
| 5098 | .any_aligned_fields = any_aligned_fields, | 5110 | .any_aligned_fields = any_aligned_fields, |
| 5111 | .fields_hash = fields_hash, | ||
| 5099 | }); | 5112 | }); |
| 5100 | 5113 | ||
| 5101 | wip_members.finishBits(bits_per_field); | 5114 | wip_members.finishBits(bits_per_field); |
| ... | @@ -5174,6 +5187,13 @@ fn unionDeclInner( | ... | @@ -5174,6 +5187,13 @@ fn unionDeclInner( |
| 5174 | var wip_members = try WipMembers.init(gpa, &astgen.scratch, decl_count, field_count, bits_per_field, max_field_size); | 5187 | var wip_members = try WipMembers.init(gpa, &astgen.scratch, decl_count, field_count, bits_per_field, max_field_size); |
| 5175 | defer wip_members.deinit(); | 5188 | defer wip_members.deinit(); |
| 5176 | 5189 | ||
| 5190 | var fields_hasher = std.zig.SrcHasher.init(.{}); | ||
| 5191 | fields_hasher.update(@tagName(layout)); | ||
| 5192 | fields_hasher.update(&.{@intFromBool(auto_enum_tok != null)}); | ||
| 5193 | if (arg_node != 0) { | ||
| 5194 | fields_hasher.update(astgen.tree.getNodeSource(arg_node)); | ||
| 5195 | } | ||
| 5196 | |||
| 5177 | var sfba = std.heap.stackFallback(256, astgen.arena); | 5197 | var sfba = std.heap.stackFallback(256, astgen.arena); |
| 5178 | const sfba_allocator = sfba.get(); | 5198 | const sfba_allocator = sfba.get(); |
| 5179 | 5199 | ||
| ... | @@ -5188,6 +5208,7 @@ fn unionDeclInner( | ... | @@ -5188,6 +5208,7 @@ fn unionDeclInner( |
| 5188 | .decl => continue, | 5208 | .decl => continue, |
| 5189 | .field => |field| field, | 5209 | .field => |field| field, |
| 5190 | }; | 5210 | }; |
| 5211 | fields_hasher.update(astgen.tree.getNodeSource(member_node)); | ||
| 5191 | member.convertToNonTupleLike(astgen.tree.nodes); | 5212 | member.convertToNonTupleLike(astgen.tree.nodes); |
| 5192 | if (member.ast.tuple_like) { | 5213 | if (member.ast.tuple_like) { |
| 5193 | return astgen.failTok(member.ast.main_token, "union field missing name", .{}); | 5214 | return astgen.failTok(member.ast.main_token, "union field missing name", .{}); |
| ... | @@ -5289,6 +5310,9 @@ fn unionDeclInner( | ... | @@ -5289,6 +5310,9 @@ fn unionDeclInner( |
| 5289 | return error.AnalysisFail; | 5310 | return error.AnalysisFail; |
| 5290 | } | 5311 | } |
| 5291 | 5312 | ||
| 5313 | var fields_hash: std.zig.SrcHash = undefined; | ||
| 5314 | fields_hasher.final(&fields_hash); | ||
| 5315 | |||
| 5292 | if (!block_scope.isEmpty()) { | 5316 | if (!block_scope.isEmpty()) { |
| 5293 | _ = try block_scope.addBreak(.break_inline, decl_inst, .void_value); | 5317 | _ = try block_scope.addBreak(.break_inline, decl_inst, .void_value); |
| 5294 | } | 5318 | } |
| ... | @@ -5305,6 +5329,7 @@ fn unionDeclInner( | ... | @@ -5305,6 +5329,7 @@ fn unionDeclInner( |
| 5305 | .decls_len = decl_count, | 5329 | .decls_len = decl_count, |
| 5306 | .auto_enum_tag = auto_enum_tok != null, | 5330 | .auto_enum_tag = auto_enum_tok != null, |
| 5307 | .any_aligned_fields = any_aligned_fields, | 5331 | .any_aligned_fields = any_aligned_fields, |
| 5332 | .fields_hash = fields_hash, | ||
| 5308 | }); | 5333 | }); |
| 5309 | 5334 | ||
| 5310 | wip_members.finishBits(bits_per_field); | 5335 | wip_members.finishBits(bits_per_field); |
| ... | @@ -5498,6 +5523,12 @@ fn containerDecl( | ... | @@ -5498,6 +5523,12 @@ fn containerDecl( |
| 5498 | var wip_members = try WipMembers.init(gpa, &astgen.scratch, @intCast(counts.decls), @intCast(counts.total_fields), bits_per_field, max_field_size); | 5523 | var wip_members = try WipMembers.init(gpa, &astgen.scratch, @intCast(counts.decls), @intCast(counts.total_fields), bits_per_field, max_field_size); |
| 5499 | defer wip_members.deinit(); | 5524 | defer wip_members.deinit(); |
| 5500 | 5525 | ||
| 5526 | var fields_hasher = std.zig.SrcHasher.init(.{}); | ||
| 5527 | if (container_decl.ast.arg != 0) { | ||
| 5528 | fields_hasher.update(tree.getNodeSource(container_decl.ast.arg)); | ||
| 5529 | } | ||
| 5530 | fields_hasher.update(&.{@intFromBool(nonexhaustive)}); | ||
| 5531 | |||
| 5501 | var sfba = std.heap.stackFallback(256, astgen.arena); | 5532 | var sfba = std.heap.stackFallback(256, astgen.arena); |
| 5502 | const sfba_allocator = sfba.get(); | 5533 | const sfba_allocator = sfba.get(); |
| 5503 | 5534 | ||
| ... | @@ -5510,6 +5541,7 @@ fn containerDecl( | ... | @@ -5510,6 +5541,7 @@ fn containerDecl( |
| 5510 | for (container_decl.ast.members) |member_node| { | 5541 | for (container_decl.ast.members) |member_node| { |
| 5511 | if (member_node == counts.nonexhaustive_node) | 5542 | if (member_node == counts.nonexhaustive_node) |
| 5512 | continue; | 5543 | continue; |
| 5544 | fields_hasher.update(tree.getNodeSource(member_node)); | ||
| 5513 | namespace.base.tag = .namespace; | 5545 | namespace.base.tag = .namespace; |
| 5514 | var member = switch (try containerMember(&block_scope, &namespace.base, &wip_members, member_node)) { | 5546 | var member = switch (try containerMember(&block_scope, &namespace.base, &wip_members, member_node)) { |
| 5515 | .decl => continue, | 5547 | .decl => continue, |
| ... | @@ -5590,6 +5622,9 @@ fn containerDecl( | ... | @@ -5590,6 +5622,9 @@ fn containerDecl( |
| 5590 | _ = try block_scope.addBreak(.break_inline, decl_inst, .void_value); | 5622 | _ = try block_scope.addBreak(.break_inline, decl_inst, .void_value); |
| 5591 | } | 5623 | } |
| 5592 | 5624 | ||
| 5625 | var fields_hash: std.zig.SrcHash = undefined; | ||
| 5626 | fields_hasher.final(&fields_hash); | ||
| 5627 | |||
| 5593 | const body = block_scope.instructionsSlice(); | 5628 | const body = block_scope.instructionsSlice(); |
| 5594 | const body_len = astgen.countBodyLenAfterFixups(body); | 5629 | const body_len = astgen.countBodyLenAfterFixups(body); |
| 5595 | 5630 | ||
| ... | @@ -5600,6 +5635,7 @@ fn containerDecl( | ... | @@ -5600,6 +5635,7 @@ fn containerDecl( |
| 5600 | .body_len = body_len, | 5635 | .body_len = body_len, |
| 5601 | .fields_len = @intCast(counts.total_fields), | 5636 | .fields_len = @intCast(counts.total_fields), |
| 5602 | .decls_len = @intCast(counts.decls), | 5637 | .decls_len = @intCast(counts.decls), |
| 5638 | .fields_hash = fields_hash, | ||
| 5603 | }); | 5639 | }); |
| 5604 | 5640 | ||
| 5605 | wip_members.finishBits(bits_per_field); | 5641 | wip_members.finishBits(bits_per_field); |
| ... | @@ -11900,8 +11936,8 @@ const GenZir = struct { | ... | @@ -11900,8 +11936,8 @@ const GenZir = struct { |
| 11900 | 11936 | ||
| 11901 | var body: []Zir.Inst.Index = &[0]Zir.Inst.Index{}; | 11937 | var body: []Zir.Inst.Index = &[0]Zir.Inst.Index{}; |
| 11902 | var ret_body: []Zir.Inst.Index = &[0]Zir.Inst.Index{}; | 11938 | var ret_body: []Zir.Inst.Index = &[0]Zir.Inst.Index{}; |
| 11903 | var src_locs_buffer: [3]u32 = undefined; | 11939 | var src_locs_and_hash_buffer: [7]u32 = undefined; |
| 11904 | var src_locs: []u32 = src_locs_buffer[0..0]; | 11940 | var src_locs_and_hash: []u32 = src_locs_and_hash_buffer[0..0]; |
| 11905 | if (args.body_gz) |body_gz| { | 11941 | if (args.body_gz) |body_gz| { |
| 11906 | const tree = astgen.tree; | 11942 | const tree = astgen.tree; |
| 11907 | const node_tags = tree.nodes.items(.tag); | 11943 | const node_tags = tree.nodes.items(.tag); |
| ... | @@ -11916,10 +11952,27 @@ const GenZir = struct { | ... | @@ -11916,10 +11952,27 @@ const GenZir = struct { |
| 11916 | const rbrace_column: u32 = @intCast(astgen.source_column); | 11952 | const rbrace_column: u32 = @intCast(astgen.source_column); |
| 11917 | 11953 | ||
| 11918 | const columns = args.lbrace_column | (rbrace_column << 16); | 11954 | const columns = args.lbrace_column | (rbrace_column << 16); |
| 11919 | src_locs_buffer[0] = args.lbrace_line; | 11955 | |
| 11920 | src_locs_buffer[1] = rbrace_line; | 11956 | const proto_hash: std.zig.SrcHash = switch (node_tags[fn_decl]) { |
| 11921 | src_locs_buffer[2] = columns; | 11957 | .fn_decl => sig_hash: { |
| 11922 | src_locs = &src_locs_buffer; | 11958 | const proto_node = node_datas[fn_decl].lhs; |
| 11959 | break :sig_hash std.zig.hashSrc(tree.getNodeSource(proto_node)); | ||
| 11960 | }, | ||
| 11961 | .test_decl => std.zig.hashSrc(""), // tests don't have a prototype | ||
| 11962 | else => unreachable, | ||
| 11963 | }; | ||
| 11964 | const proto_hash_arr: [4]u32 = @bitCast(proto_hash); | ||
| 11965 | |||
| 11966 | src_locs_and_hash_buffer = .{ | ||
| 11967 | args.lbrace_line, | ||
| 11968 | rbrace_line, | ||
| 11969 | columns, | ||
| 11970 | proto_hash_arr[0], | ||
| 11971 | proto_hash_arr[1], | ||
| 11972 | proto_hash_arr[2], | ||
| 11973 | proto_hash_arr[3], | ||
| 11974 | }; | ||
| 11975 | src_locs_and_hash = &src_locs_and_hash_buffer; | ||
| 11923 | 11976 | ||
| 11924 | body = body_gz.instructionsSlice(); | 11977 | body = body_gz.instructionsSlice(); |
| 11925 | if (args.ret_gz) |ret_gz| | 11978 | if (args.ret_gz) |ret_gz| |
| ... | @@ -11953,7 +12006,7 @@ const GenZir = struct { | ... | @@ -11953,7 +12006,7 @@ const GenZir = struct { |
| 11953 | fancyFnExprExtraLen(astgen, section_body, args.section_ref) + | 12006 | fancyFnExprExtraLen(astgen, section_body, args.section_ref) + |
| 11954 | fancyFnExprExtraLen(astgen, cc_body, args.cc_ref) + | 12007 | fancyFnExprExtraLen(astgen, cc_body, args.cc_ref) + |
| 11955 | fancyFnExprExtraLen(astgen, ret_body, ret_ref) + | 12008 | fancyFnExprExtraLen(astgen, ret_body, ret_ref) + |
| 11956 | body_len + src_locs.len + | 12009 | body_len + src_locs_and_hash.len + |
| 11957 | @intFromBool(args.lib_name != .empty) + | 12010 | @intFromBool(args.lib_name != .empty) + |
| 11958 | @intFromBool(args.noalias_bits != 0), | 12011 | @intFromBool(args.noalias_bits != 0), |
| 11959 | ); | 12012 | ); |
| ... | @@ -12040,7 +12093,7 @@ const GenZir = struct { | ... | @@ -12040,7 +12093,7 @@ const GenZir = struct { |
| 12040 | } | 12093 | } |
| 12041 | 12094 | ||
| 12042 | astgen.appendBodyWithFixups(body); | 12095 | astgen.appendBodyWithFixups(body); |
| 12043 | astgen.extra.appendSliceAssumeCapacity(src_locs); | 12096 | astgen.extra.appendSliceAssumeCapacity(src_locs_and_hash); |
| 12044 | 12097 | ||
| 12045 | // Order is important when unstacking. | 12098 | // Order is important when unstacking. |
| 12046 | if (args.body_gz) |body_gz| body_gz.unstack(); | 12099 | if (args.body_gz) |body_gz| body_gz.unstack(); |
| ... | @@ -12068,7 +12121,7 @@ const GenZir = struct { | ... | @@ -12068,7 +12121,7 @@ const GenZir = struct { |
| 12068 | gpa, | 12121 | gpa, |
| 12069 | @typeInfo(Zir.Inst.Func).Struct.fields.len + 1 + | 12122 | @typeInfo(Zir.Inst.Func).Struct.fields.len + 1 + |
| 12070 | fancyFnExprExtraLen(astgen, ret_body, ret_ref) + | 12123 | fancyFnExprExtraLen(astgen, ret_body, ret_ref) + |
| 12071 | body_len + src_locs.len, | 12124 | body_len + src_locs_and_hash.len, |
| 12072 | ); | 12125 | ); |
| 12073 | 12126 | ||
| 12074 | const ret_body_len = if (ret_body.len != 0) | 12127 | const ret_body_len = if (ret_body.len != 0) |
| ... | @@ -12092,7 +12145,7 @@ const GenZir = struct { | ... | @@ -12092,7 +12145,7 @@ const GenZir = struct { |
| 12092 | astgen.extra.appendAssumeCapacity(@intFromEnum(ret_ref)); | 12145 | astgen.extra.appendAssumeCapacity(@intFromEnum(ret_ref)); |
| 12093 | } | 12146 | } |
| 12094 | astgen.appendBodyWithFixups(body); | 12147 | astgen.appendBodyWithFixups(body); |
| 12095 | astgen.extra.appendSliceAssumeCapacity(src_locs); | 12148 | astgen.extra.appendSliceAssumeCapacity(src_locs_and_hash); |
| 12096 | 12149 | ||
| 12097 | // Order is important when unstacking. | 12150 | // Order is important when unstacking. |
| 12098 | if (args.body_gz) |body_gz| body_gz.unstack(); | 12151 | if (args.body_gz) |body_gz| body_gz.unstack(); |
| ... | @@ -12853,12 +12906,20 @@ const GenZir = struct { | ... | @@ -12853,12 +12906,20 @@ const GenZir = struct { |
| 12853 | any_comptime_fields: bool, | 12906 | any_comptime_fields: bool, |
| 12854 | any_default_inits: bool, | 12907 | any_default_inits: bool, |
| 12855 | any_aligned_fields: bool, | 12908 | any_aligned_fields: bool, |
| 12909 | fields_hash: std.zig.SrcHash, | ||
| 12856 | }) !void { | 12910 | }) !void { |
| 12857 | const astgen = gz.astgen; | 12911 | const astgen = gz.astgen; |
| 12858 | const gpa = astgen.gpa; | 12912 | const gpa = astgen.gpa; |
| 12859 | 12913 | ||
| 12860 | try astgen.extra.ensureUnusedCapacity(gpa, 6); | 12914 | const fields_hash_arr: [4]u32 = @bitCast(args.fields_hash); |
| 12861 | const payload_index: u32 = @intCast(astgen.extra.items.len); | 12915 | |
| 12916 | try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.StructDecl).Struct.fields.len + 6); | ||
| 12917 | const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.StructDecl{ | ||
| 12918 | .fields_hash_0 = fields_hash_arr[0], | ||
| 12919 | .fields_hash_1 = fields_hash_arr[1], | ||
| 12920 | .fields_hash_2 = fields_hash_arr[2], | ||
| 12921 | .fields_hash_3 = fields_hash_arr[3], | ||
| 12922 | }); | ||
| 12862 | 12923 | ||
| 12863 | if (args.src_node != 0) { | 12924 | if (args.src_node != 0) { |
| 12864 | const node_offset = gz.nodeIndexToRelative(args.src_node); | 12925 | const node_offset = gz.nodeIndexToRelative(args.src_node); |
| ... | @@ -12908,12 +12969,20 @@ const GenZir = struct { | ... | @@ -12908,12 +12969,20 @@ const GenZir = struct { |
| 12908 | layout: std.builtin.Type.ContainerLayout, | 12969 | layout: std.builtin.Type.ContainerLayout, |
| 12909 | auto_enum_tag: bool, | 12970 | auto_enum_tag: bool, |
| 12910 | any_aligned_fields: bool, | 12971 | any_aligned_fields: bool, |
| 12972 | fields_hash: std.zig.SrcHash, | ||
| 12911 | }) !void { | 12973 | }) !void { |
| 12912 | const astgen = gz.astgen; | 12974 | const astgen = gz.astgen; |
| 12913 | const gpa = astgen.gpa; | 12975 | const gpa = astgen.gpa; |
| 12914 | 12976 | ||
| 12915 | try astgen.extra.ensureUnusedCapacity(gpa, 5); | 12977 | const fields_hash_arr: [4]u32 = @bitCast(args.fields_hash); |
| 12916 | const payload_index: u32 = @intCast(astgen.extra.items.len); | 12978 | |
| 12979 | try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.UnionDecl).Struct.fields.len + 5); | ||
| 12980 | const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.UnionDecl{ | ||
| 12981 | .fields_hash_0 = fields_hash_arr[0], | ||
| 12982 | .fields_hash_1 = fields_hash_arr[1], | ||
| 12983 | .fields_hash_2 = fields_hash_arr[2], | ||
| 12984 | .fields_hash_3 = fields_hash_arr[3], | ||
| 12985 | }); | ||
| 12917 | 12986 | ||
| 12918 | if (args.src_node != 0) { | 12987 | if (args.src_node != 0) { |
| 12919 | const node_offset = gz.nodeIndexToRelative(args.src_node); | 12988 | const node_offset = gz.nodeIndexToRelative(args.src_node); |
| ... | @@ -12958,12 +13027,20 @@ const GenZir = struct { | ... | @@ -12958,12 +13027,20 @@ const GenZir = struct { |
| 12958 | fields_len: u32, | 13027 | fields_len: u32, |
| 12959 | decls_len: u32, | 13028 | decls_len: u32, |
| 12960 | nonexhaustive: bool, | 13029 | nonexhaustive: bool, |
| 13030 | fields_hash: std.zig.SrcHash, | ||
| 12961 | }) !void { | 13031 | }) !void { |
| 12962 | const astgen = gz.astgen; | 13032 | const astgen = gz.astgen; |
| 12963 | const gpa = astgen.gpa; | 13033 | const gpa = astgen.gpa; |
| 12964 | 13034 | ||
| 12965 | try astgen.extra.ensureUnusedCapacity(gpa, 5); | 13035 | const fields_hash_arr: [4]u32 = @bitCast(args.fields_hash); |
| 12966 | const payload_index: u32 = @intCast(astgen.extra.items.len); | 13036 | |
| 13037 | try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.EnumDecl).Struct.fields.len + 5); | ||
| 13038 | const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.EnumDecl{ | ||
| 13039 | .fields_hash_0 = fields_hash_arr[0], | ||
| 13040 | .fields_hash_1 = fields_hash_arr[1], | ||
| 13041 | .fields_hash_2 = fields_hash_arr[2], | ||
| 13042 | .fields_hash_3 = fields_hash_arr[3], | ||
| 13043 | }); | ||
| 12967 | 13044 | ||
| 12968 | if (args.src_node != 0) { | 13045 | if (args.src_node != 0) { |
| 12969 | const node_offset = gz.nodeIndexToRelative(args.src_node); | 13046 | const node_offset = gz.nodeIndexToRelative(args.src_node); |
src/Autodoc.zig+3-3| ... | @@ -3497,7 +3497,7 @@ fn walkInstruction( | ... | @@ -3497,7 +3497,7 @@ fn walkInstruction( |
| 3497 | }; | 3497 | }; |
| 3498 | 3498 | ||
| 3499 | const small = @as(Zir.Inst.UnionDecl.Small, @bitCast(extended.small)); | 3499 | const small = @as(Zir.Inst.UnionDecl.Small, @bitCast(extended.small)); |
| 3500 | var extra_index: usize = extended.operand; | 3500 | var extra_index: usize = extended.operand + @typeInfo(Zir.Inst.UnionDecl).Struct.fields.len; |
| 3501 | 3501 | ||
| 3502 | const src_node: ?i32 = if (small.has_src_node) blk: { | 3502 | const src_node: ?i32 = if (small.has_src_node) blk: { |
| 3503 | const src_node = @as(i32, @bitCast(file.zir.extra[extra_index])); | 3503 | const src_node = @as(i32, @bitCast(file.zir.extra[extra_index])); |
| ... | @@ -3627,7 +3627,7 @@ fn walkInstruction( | ... | @@ -3627,7 +3627,7 @@ fn walkInstruction( |
| 3627 | }; | 3627 | }; |
| 3628 | 3628 | ||
| 3629 | const small = @as(Zir.Inst.EnumDecl.Small, @bitCast(extended.small)); | 3629 | const small = @as(Zir.Inst.EnumDecl.Small, @bitCast(extended.small)); |
| 3630 | var extra_index: usize = extended.operand; | 3630 | var extra_index: usize = extended.operand + @typeInfo(Zir.Inst.EnumDecl).Struct.fields.len; |
| 3631 | 3631 | ||
| 3632 | const src_node: ?i32 = if (small.has_src_node) blk: { | 3632 | const src_node: ?i32 = if (small.has_src_node) blk: { |
| 3633 | const src_node = @as(i32, @bitCast(file.zir.extra[extra_index])); | 3633 | const src_node = @as(i32, @bitCast(file.zir.extra[extra_index])); |
| ... | @@ -3778,7 +3778,7 @@ fn walkInstruction( | ... | @@ -3778,7 +3778,7 @@ fn walkInstruction( |
| 3778 | }; | 3778 | }; |
| 3779 | 3779 | ||
| 3780 | const small = @as(Zir.Inst.StructDecl.Small, @bitCast(extended.small)); | 3780 | const small = @as(Zir.Inst.StructDecl.Small, @bitCast(extended.small)); |
| 3781 | var extra_index: usize = extended.operand; | 3781 | var extra_index: usize = extended.operand + @typeInfo(Zir.Inst.StructDecl).Struct.fields.len; |
| 3782 | 3782 | ||
| 3783 | const src_node: ?i32 = if (small.has_src_node) blk: { | 3783 | const src_node: ?i32 = if (small.has_src_node) blk: { |
| 3784 | const src_node = @as(i32, @bitCast(file.zir.extra[extra_index])); | 3784 | const src_node = @as(i32, @bitCast(file.zir.extra[extra_index])); |
src/Compilation.zig+48-13| ... | @@ -156,6 +156,7 @@ time_report: bool, | ... | @@ -156,6 +156,7 @@ time_report: bool, |
| 156 | stack_report: bool, | 156 | stack_report: bool, |
| 157 | debug_compiler_runtime_libs: bool, | 157 | debug_compiler_runtime_libs: bool, |
| 158 | debug_compile_errors: bool, | 158 | debug_compile_errors: bool, |
| 159 | debug_incremental: bool, | ||
| 159 | job_queued_compiler_rt_lib: bool = false, | 160 | job_queued_compiler_rt_lib: bool = false, |
| 160 | job_queued_compiler_rt_obj: bool = false, | 161 | job_queued_compiler_rt_obj: bool = false, |
| 161 | job_queued_update_builtin_zig: bool, | 162 | job_queued_update_builtin_zig: bool, |
| ... | @@ -1079,6 +1080,7 @@ pub const CreateOptions = struct { | ... | @@ -1079,6 +1080,7 @@ pub const CreateOptions = struct { |
| 1079 | verbose_llvm_cpu_features: bool = false, | 1080 | verbose_llvm_cpu_features: bool = false, |
| 1080 | debug_compiler_runtime_libs: bool = false, | 1081 | debug_compiler_runtime_libs: bool = false, |
| 1081 | debug_compile_errors: bool = false, | 1082 | debug_compile_errors: bool = false, |
| 1083 | debug_incremental: bool = false, | ||
| 1082 | /// Normally when you create a `Compilation`, Zig will automatically build | 1084 | /// Normally when you create a `Compilation`, Zig will automatically build |
| 1083 | /// and link in required dependencies, such as compiler-rt and libc. When | 1085 | /// and link in required dependencies, such as compiler-rt and libc. When |
| 1084 | /// building such dependencies themselves, this flag must be set to avoid | 1086 | /// building such dependencies themselves, this flag must be set to avoid |
| ... | @@ -1508,6 +1510,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil | ... | @@ -1508,6 +1510,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil |
| 1508 | .test_name_prefix = options.test_name_prefix, | 1510 | .test_name_prefix = options.test_name_prefix, |
| 1509 | .debug_compiler_runtime_libs = options.debug_compiler_runtime_libs, | 1511 | .debug_compiler_runtime_libs = options.debug_compiler_runtime_libs, |
| 1510 | .debug_compile_errors = options.debug_compile_errors, | 1512 | .debug_compile_errors = options.debug_compile_errors, |
| 1513 | .debug_incremental = options.debug_incremental, | ||
| 1511 | .libcxx_abi_version = options.libcxx_abi_version, | 1514 | .libcxx_abi_version = options.libcxx_abi_version, |
| 1512 | .root_name = root_name, | 1515 | .root_name = root_name, |
| 1513 | .sysroot = sysroot, | 1516 | .sysroot = sysroot, |
| ... | @@ -2141,7 +2144,6 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void | ... | @@ -2141,7 +2144,6 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void |
| 2141 | 2144 | ||
| 2142 | if (comp.module) |module| { | 2145 | if (comp.module) |module| { |
| 2143 | module.compile_log_text.shrinkAndFree(gpa, 0); | 2146 | module.compile_log_text.shrinkAndFree(gpa, 0); |
| 2144 | module.generation += 1; | ||
| 2145 | 2147 | ||
| 2146 | // Make sure std.zig is inside the import_table. We unconditionally need | 2148 | // Make sure std.zig is inside the import_table. We unconditionally need |
| 2147 | // it for start.zig. | 2149 | // it for start.zig. |
| ... | @@ -2807,6 +2809,13 @@ const Header = extern struct { | ... | @@ -2807,6 +2809,13 @@ const Header = extern struct { |
| 2807 | limbs_len: u32, | 2809 | limbs_len: u32, |
| 2808 | string_bytes_len: u32, | 2810 | string_bytes_len: u32, |
| 2809 | tracked_insts_len: u32, | 2811 | tracked_insts_len: u32, |
| 2812 | src_hash_deps_len: u32, | ||
| 2813 | decl_val_deps_len: u32, | ||
| 2814 | namespace_deps_len: u32, | ||
| 2815 | namespace_name_deps_len: u32, | ||
| 2816 | first_dependency_len: u32, | ||
| 2817 | dep_entries_len: u32, | ||
| 2818 | free_dep_entries_len: u32, | ||
| 2810 | }, | 2819 | }, |
| 2811 | }; | 2820 | }; |
| 2812 | 2821 | ||
| ... | @@ -2814,7 +2823,7 @@ const Header = extern struct { | ... | @@ -2814,7 +2823,7 @@ const Header = extern struct { |
| 2814 | /// saved, such as the target and most CLI flags. A cache hit will only occur | 2823 | /// saved, such as the target and most CLI flags. A cache hit will only occur |
| 2815 | /// when subsequent compiler invocations use the same set of flags. | 2824 | /// when subsequent compiler invocations use the same set of flags. |
| 2816 | pub fn saveState(comp: *Compilation) !void { | 2825 | pub fn saveState(comp: *Compilation) !void { |
| 2817 | var bufs_list: [7]std.os.iovec_const = undefined; | 2826 | var bufs_list: [19]std.os.iovec_const = undefined; |
| 2818 | var bufs_len: usize = 0; | 2827 | var bufs_len: usize = 0; |
| 2819 | 2828 | ||
| 2820 | const lf = comp.bin_file orelse return; | 2829 | const lf = comp.bin_file orelse return; |
| ... | @@ -2828,6 +2837,13 @@ pub fn saveState(comp: *Compilation) !void { | ... | @@ -2828,6 +2837,13 @@ pub fn saveState(comp: *Compilation) !void { |
| 2828 | .limbs_len = @intCast(ip.limbs.items.len), | 2837 | .limbs_len = @intCast(ip.limbs.items.len), |
| 2829 | .string_bytes_len = @intCast(ip.string_bytes.items.len), | 2838 | .string_bytes_len = @intCast(ip.string_bytes.items.len), |
| 2830 | .tracked_insts_len = @intCast(ip.tracked_insts.count()), | 2839 | .tracked_insts_len = @intCast(ip.tracked_insts.count()), |
| 2840 | .src_hash_deps_len = @intCast(ip.src_hash_deps.count()), | ||
| 2841 | .decl_val_deps_len = @intCast(ip.decl_val_deps.count()), | ||
| 2842 | .namespace_deps_len = @intCast(ip.namespace_deps.count()), | ||
| 2843 | .namespace_name_deps_len = @intCast(ip.namespace_name_deps.count()), | ||
| 2844 | .first_dependency_len = @intCast(ip.first_dependency.count()), | ||
| 2845 | .dep_entries_len = @intCast(ip.dep_entries.items.len), | ||
| 2846 | .free_dep_entries_len = @intCast(ip.free_dep_entries.items.len), | ||
| 2831 | }, | 2847 | }, |
| 2832 | }; | 2848 | }; |
| 2833 | addBuf(&bufs_list, &bufs_len, mem.asBytes(&header)); | 2849 | addBuf(&bufs_list, &bufs_len, mem.asBytes(&header)); |
| ... | @@ -2838,6 +2854,20 @@ pub fn saveState(comp: *Compilation) !void { | ... | @@ -2838,6 +2854,20 @@ pub fn saveState(comp: *Compilation) !void { |
| 2838 | addBuf(&bufs_list, &bufs_len, ip.string_bytes.items); | 2854 | addBuf(&bufs_list, &bufs_len, ip.string_bytes.items); |
| 2839 | addBuf(&bufs_list, &bufs_len, mem.sliceAsBytes(ip.tracked_insts.keys())); | 2855 | addBuf(&bufs_list, &bufs_len, mem.sliceAsBytes(ip.tracked_insts.keys())); |
| 2840 | 2856 | ||
| 2857 | addBuf(&bufs_list, &bufs_len, mem.sliceAsBytes(ip.src_hash_deps.keys())); | ||
| 2858 | addBuf(&bufs_list, &bufs_len, mem.sliceAsBytes(ip.src_hash_deps.values())); | ||
| 2859 | addBuf(&bufs_list, &bufs_len, mem.sliceAsBytes(ip.decl_val_deps.keys())); | ||
| 2860 | addBuf(&bufs_list, &bufs_len, mem.sliceAsBytes(ip.decl_val_deps.values())); | ||
| 2861 | addBuf(&bufs_list, &bufs_len, mem.sliceAsBytes(ip.namespace_deps.keys())); | ||
| 2862 | addBuf(&bufs_list, &bufs_len, mem.sliceAsBytes(ip.namespace_deps.values())); | ||
| 2863 | addBuf(&bufs_list, &bufs_len, mem.sliceAsBytes(ip.namespace_name_deps.keys())); | ||
| 2864 | addBuf(&bufs_list, &bufs_len, mem.sliceAsBytes(ip.namespace_name_deps.values())); | ||
| 2865 | |||
| 2866 | addBuf(&bufs_list, &bufs_len, mem.sliceAsBytes(ip.first_dependency.keys())); | ||
| 2867 | addBuf(&bufs_list, &bufs_len, mem.sliceAsBytes(ip.first_dependency.values())); | ||
| 2868 | addBuf(&bufs_list, &bufs_len, mem.sliceAsBytes(ip.dep_entries.items)); | ||
| 2869 | addBuf(&bufs_list, &bufs_len, mem.sliceAsBytes(ip.free_dep_entries.items)); | ||
| 2870 | |||
| 2841 | // TODO: compilation errors | 2871 | // TODO: compilation errors |
| 2842 | // TODO: files | 2872 | // TODO: files |
| 2843 | // TODO: namespaces | 2873 | // TODO: namespaces |
| ... | @@ -3463,9 +3493,7 @@ pub fn performAllTheWork( | ... | @@ -3463,9 +3493,7 @@ pub fn performAllTheWork( |
| 3463 | 3493 | ||
| 3464 | if (comp.module) |mod| { | 3494 | if (comp.module) |mod| { |
| 3465 | try reportMultiModuleErrors(mod); | 3495 | try reportMultiModuleErrors(mod); |
| 3466 | } | 3496 | try mod.flushRetryableFailures(); |
| 3467 | |||
| 3468 | if (comp.module) |mod| { | ||
| 3469 | mod.sema_prog_node = main_progress_node.start("Semantic Analysis", 0); | 3497 | mod.sema_prog_node = main_progress_node.start("Semantic Analysis", 0); |
| 3470 | mod.sema_prog_node.activate(); | 3498 | mod.sema_prog_node.activate(); |
| 3471 | } | 3499 | } |
| ... | @@ -3486,6 +3514,17 @@ pub fn performAllTheWork( | ... | @@ -3486,6 +3514,17 @@ pub fn performAllTheWork( |
| 3486 | try processOneJob(comp, work_item, main_progress_node); | 3514 | try processOneJob(comp, work_item, main_progress_node); |
| 3487 | continue; | 3515 | continue; |
| 3488 | } | 3516 | } |
| 3517 | if (comp.module) |zcu| { | ||
| 3518 | // If there's no work queued, check if there's anything outdated | ||
| 3519 | // which we need to work on, and queue it if so. | ||
| 3520 | if (try zcu.findOutdatedToAnalyze()) |outdated| { | ||
| 3521 | switch (outdated.unwrap()) { | ||
| 3522 | .decl => |decl| try comp.work_queue.writeItem(.{ .analyze_decl = decl }), | ||
| 3523 | .func => |func| try comp.work_queue.writeItem(.{ .codegen_func = func }), | ||
| 3524 | } | ||
| 3525 | continue; | ||
| 3526 | } | ||
| 3527 | } | ||
| 3489 | break; | 3528 | break; |
| 3490 | } | 3529 | } |
| 3491 | 3530 | ||
| ... | @@ -3509,17 +3548,14 @@ fn processOneJob(comp: *Compilation, job: Job, prog_node: *std.Progress.Node) !v | ... | @@ -3509,17 +3548,14 @@ fn processOneJob(comp: *Compilation, job: Job, prog_node: *std.Progress.Node) !v |
| 3509 | switch (decl.analysis) { | 3548 | switch (decl.analysis) { |
| 3510 | .unreferenced => unreachable, | 3549 | .unreferenced => unreachable, |
| 3511 | .in_progress => unreachable, | 3550 | .in_progress => unreachable, |
| 3512 | .outdated => unreachable, | ||
| 3513 | 3551 | ||
| 3514 | .file_failure, | 3552 | .file_failure, |
| 3515 | .sema_failure, | 3553 | .sema_failure, |
| 3516 | .liveness_failure, | ||
| 3517 | .codegen_failure, | 3554 | .codegen_failure, |
| 3518 | .dependency_failure, | 3555 | .dependency_failure, |
| 3519 | .sema_failure_retryable, | ||
| 3520 | => return, | 3556 | => return, |
| 3521 | 3557 | ||
| 3522 | .complete, .codegen_failure_retryable => { | 3558 | .complete => { |
| 3523 | const named_frame = tracy.namedFrame("codegen_decl"); | 3559 | const named_frame = tracy.namedFrame("codegen_decl"); |
| 3524 | defer named_frame.end(); | 3560 | defer named_frame.end(); |
| 3525 | 3561 | ||
| ... | @@ -3554,17 +3590,15 @@ fn processOneJob(comp: *Compilation, job: Job, prog_node: *std.Progress.Node) !v | ... | @@ -3554,17 +3590,15 @@ fn processOneJob(comp: *Compilation, job: Job, prog_node: *std.Progress.Node) !v |
| 3554 | switch (decl.analysis) { | 3590 | switch (decl.analysis) { |
| 3555 | .unreferenced => unreachable, | 3591 | .unreferenced => unreachable, |
| 3556 | .in_progress => unreachable, | 3592 | .in_progress => unreachable, |
| 3557 | .outdated => unreachable, | ||
| 3558 | 3593 | ||
| 3559 | .file_failure, | 3594 | .file_failure, |
| 3560 | .sema_failure, | 3595 | .sema_failure, |
| 3561 | .dependency_failure, | 3596 | .dependency_failure, |
| 3562 | .sema_failure_retryable, | ||
| 3563 | => return, | 3597 | => return, |
| 3564 | 3598 | ||
| 3565 | // emit-h only requires semantic analysis of the Decl to be complete, | 3599 | // emit-h only requires semantic analysis of the Decl to be complete, |
| 3566 | // it does not depend on machine code generation to succeed. | 3600 | // it does not depend on machine code generation to succeed. |
| 3567 | .liveness_failure, .codegen_failure, .codegen_failure_retryable, .complete => { | 3601 | .codegen_failure, .complete => { |
| 3568 | const named_frame = tracy.namedFrame("emit_h_decl"); | 3602 | const named_frame = tracy.namedFrame("emit_h_decl"); |
| 3569 | defer named_frame.end(); | 3603 | defer named_frame.end(); |
| 3570 | 3604 | ||
| ... | @@ -3636,7 +3670,8 @@ fn processOneJob(comp: *Compilation, job: Job, prog_node: *std.Progress.Node) !v | ... | @@ -3636,7 +3670,8 @@ fn processOneJob(comp: *Compilation, job: Job, prog_node: *std.Progress.Node) !v |
| 3636 | "unable to update line number: {s}", | 3670 | "unable to update line number: {s}", |
| 3637 | .{@errorName(err)}, | 3671 | .{@errorName(err)}, |
| 3638 | )); | 3672 | )); |
| 3639 | decl.analysis = .codegen_failure_retryable; | 3673 | decl.analysis = .codegen_failure; |
| 3674 | try module.retryable_failures.append(gpa, InternPool.Depender.wrap(.{ .decl = decl_index })); | ||
| 3640 | }; | 3675 | }; |
| 3641 | }, | 3676 | }, |
| 3642 | .analyze_mod => |pkg| { | 3677 | .analyze_mod => |pkg| { |
src/InternPool.zig+283-16| ... | @@ -58,6 +58,38 @@ string_table: std.HashMapUnmanaged( | ... | @@ -58,6 +58,38 @@ string_table: std.HashMapUnmanaged( |
| 58 | /// persists across incremental updates. | 58 | /// persists across incremental updates. |
| 59 | tracked_insts: std.AutoArrayHashMapUnmanaged(TrackedInst, void) = .{}, | 59 | tracked_insts: std.AutoArrayHashMapUnmanaged(TrackedInst, void) = .{}, |
| 60 | 60 | ||
| 61 | /// Dependencies on the source code hash associated with a ZIR instruction. | ||
| 62 | /// * For a `declaration`, this is the entire declaration body. | ||
| 63 | /// * For a `struct_decl`, `union_decl`, etc, this is the source of the fields (but not declarations). | ||
| 64 | /// * For a `func`, this is the source of the full function signature. | ||
| 65 | /// These are also invalidated if tracking fails for this instruction. | ||
| 66 | /// Value is index into `dep_entries` of the first dependency on this hash. | ||
| 67 | src_hash_deps: std.AutoArrayHashMapUnmanaged(TrackedInst.Index, DepEntry.Index) = .{}, | ||
| 68 | /// Dependencies on the value of a Decl. | ||
| 69 | /// Value is index into `dep_entries` of the first dependency on this Decl value. | ||
| 70 | decl_val_deps: std.AutoArrayHashMapUnmanaged(DeclIndex, DepEntry.Index) = .{}, | ||
| 71 | /// Dependencies on the full set of names in a ZIR namespace. | ||
| 72 | /// Key refers to a `struct_decl`, `union_decl`, etc. | ||
| 73 | /// Value is index into `dep_entries` of the first dependency on this namespace. | ||
| 74 | namespace_deps: std.AutoArrayHashMapUnmanaged(TrackedInst.Index, DepEntry.Index) = .{}, | ||
| 75 | /// Dependencies on the (non-)existence of some name in a namespace. | ||
| 76 | /// Value is index into `dep_entries` of the first dependency on this name. | ||
| 77 | namespace_name_deps: std.AutoArrayHashMapUnmanaged(NamespaceNameKey, DepEntry.Index) = .{}, | ||
| 78 | |||
| 79 | /// Given a `Depender`, points to an entry in `dep_entries` whose `depender` | ||
| 80 | /// matches. The `next_dependee` field can be used to iterate all such entries | ||
| 81 | /// and remove them from the corresponding lists. | ||
| 82 | first_dependency: std.AutoArrayHashMapUnmanaged(Depender, DepEntry.Index) = .{}, | ||
| 83 | |||
| 84 | /// Stores dependency information. The hashmaps declared above are used to look | ||
| 85 | /// up entries in this list as required. This is not stored in `extra` so that | ||
| 86 | /// we can use `free_dep_entries` to track free indices, since dependencies are | ||
| 87 | /// removed frequently. | ||
| 88 | dep_entries: std.ArrayListUnmanaged(DepEntry) = .{}, | ||
| 89 | /// Stores unused indices in `dep_entries` which can be reused without a full | ||
| 90 | /// garbage collection pass. | ||
| 91 | free_dep_entries: std.ArrayListUnmanaged(DepEntry.Index) = .{}, | ||
| 92 | |||
| 61 | pub const TrackedInst = extern struct { | 93 | pub const TrackedInst = extern struct { |
| 62 | path_digest: Cache.BinDigest, | 94 | path_digest: Cache.BinDigest, |
| 63 | inst: Zir.Inst.Index, | 95 | inst: Zir.Inst.Index, |
| ... | @@ -70,6 +102,19 @@ pub const TrackedInst = extern struct { | ... | @@ -70,6 +102,19 @@ pub const TrackedInst = extern struct { |
| 70 | pub fn resolve(i: TrackedInst.Index, ip: *const InternPool) Zir.Inst.Index { | 102 | pub fn resolve(i: TrackedInst.Index, ip: *const InternPool) Zir.Inst.Index { |
| 71 | return ip.tracked_insts.keys()[@intFromEnum(i)].inst; | 103 | return ip.tracked_insts.keys()[@intFromEnum(i)].inst; |
| 72 | } | 104 | } |
| 105 | pub fn toOptional(i: TrackedInst.Index) Optional { | ||
| 106 | return @enumFromInt(@intFromEnum(i)); | ||
| 107 | } | ||
| 108 | pub const Optional = enum(u32) { | ||
| 109 | none = std.math.maxInt(u32), | ||
| 110 | _, | ||
| 111 | pub fn unwrap(opt: Optional) ?TrackedInst.Index { | ||
| 112 | return switch (opt) { | ||
| 113 | .none => null, | ||
| 114 | _ => @enumFromInt(@intFromEnum(opt)), | ||
| 115 | }; | ||
| 116 | } | ||
| 117 | }; | ||
| 73 | }; | 118 | }; |
| 74 | }; | 119 | }; |
| 75 | 120 | ||
| ... | @@ -82,6 +127,202 @@ pub fn trackZir(ip: *InternPool, gpa: Allocator, file: *Module.File, inst: Zir.I | ... | @@ -82,6 +127,202 @@ pub fn trackZir(ip: *InternPool, gpa: Allocator, file: *Module.File, inst: Zir.I |
| 82 | return @enumFromInt(gop.index); | 127 | return @enumFromInt(gop.index); |
| 83 | } | 128 | } |
| 84 | 129 | ||
| 130 | /// Reperesents the "source" of a dependency edge, i.e. either a Decl or a | ||
| 131 | /// runtime function (represented as an InternPool index). | ||
| 132 | /// MSB is 0 for a Decl, 1 for a function. | ||
| 133 | pub const Depender = enum(u32) { | ||
| 134 | _, | ||
| 135 | pub const Unwrapped = union(enum) { | ||
| 136 | decl: DeclIndex, | ||
| 137 | func: InternPool.Index, | ||
| 138 | }; | ||
| 139 | pub fn unwrap(dep: Depender) Unwrapped { | ||
| 140 | const tag: u1 = @truncate(@intFromEnum(dep) >> 31); | ||
| 141 | const val: u31 = @truncate(@intFromEnum(dep)); | ||
| 142 | return switch (tag) { | ||
| 143 | 0 => .{ .decl = @enumFromInt(val) }, | ||
| 144 | 1 => .{ .func = @enumFromInt(val) }, | ||
| 145 | }; | ||
| 146 | } | ||
| 147 | pub fn wrap(raw: Unwrapped) Depender { | ||
| 148 | return @enumFromInt(switch (raw) { | ||
| 149 | .decl => |decl| @intFromEnum(decl), | ||
| 150 | .func => |func| (1 << 31) | @intFromEnum(func), | ||
| 151 | }); | ||
| 152 | } | ||
| 153 | pub fn toOptional(dep: Depender) Optional { | ||
| 154 | return @enumFromInt(@intFromEnum(dep)); | ||
| 155 | } | ||
| 156 | pub const Optional = enum(u32) { | ||
| 157 | none = std.math.maxInt(u32), | ||
| 158 | _, | ||
| 159 | pub fn unwrap(opt: Optional) ?Depender { | ||
| 160 | return switch (opt) { | ||
| 161 | .none => null, | ||
| 162 | _ => @enumFromInt(@intFromEnum(opt)), | ||
| 163 | }; | ||
| 164 | } | ||
| 165 | }; | ||
| 166 | }; | ||
| 167 | |||
| 168 | pub const Dependee = union(enum) { | ||
| 169 | src_hash: TrackedInst.Index, | ||
| 170 | decl_val: DeclIndex, | ||
| 171 | namespace: TrackedInst.Index, | ||
| 172 | namespace_name: NamespaceNameKey, | ||
| 173 | }; | ||
| 174 | |||
| 175 | pub fn removeDependenciesForDepender(ip: *InternPool, gpa: Allocator, depender: Depender) void { | ||
| 176 | var opt_idx = (ip.first_dependency.fetchSwapRemove(depender) orelse return).value.toOptional(); | ||
| 177 | |||
| 178 | while (opt_idx.unwrap()) |idx| { | ||
| 179 | const dep = ip.dep_entries.items[@intFromEnum(idx)]; | ||
| 180 | opt_idx = dep.next_dependee; | ||
| 181 | |||
| 182 | const prev_idx = dep.prev.unwrap() orelse { | ||
| 183 | // This entry is the start of a list in some `*_deps`. | ||
| 184 | // We cannot easily remove this mapping, so this must remain as a dummy entry. | ||
| 185 | ip.dep_entries.items[@intFromEnum(idx)].depender = .none; | ||
| 186 | continue; | ||
| 187 | }; | ||
| 188 | |||
| 189 | ip.dep_entries.items[@intFromEnum(prev_idx)].next = dep.next; | ||
| 190 | if (dep.next.unwrap()) |next_idx| { | ||
| 191 | ip.dep_entries.items[@intFromEnum(next_idx)].prev = dep.prev; | ||
| 192 | } | ||
| 193 | |||
| 194 | ip.free_dep_entries.append(gpa, idx) catch { | ||
| 195 | // This memory will be reclaimed on the next garbage collection. | ||
| 196 | // Thus, we do not need to propagate this error. | ||
| 197 | }; | ||
| 198 | } | ||
| 199 | } | ||
| 200 | |||
| 201 | pub const DependencyIterator = struct { | ||
| 202 | ip: *const InternPool, | ||
| 203 | next_entry: DepEntry.Index.Optional, | ||
| 204 | pub fn next(it: *DependencyIterator) ?Depender { | ||
| 205 | const idx = it.next_entry.unwrap() orelse return null; | ||
| 206 | const entry = it.ip.dep_entries.items[@intFromEnum(idx)]; | ||
| 207 | it.next_entry = entry.next; | ||
| 208 | return entry.depender.unwrap().?; | ||
| 209 | } | ||
| 210 | }; | ||
| 211 | |||
| 212 | pub fn dependencyIterator(ip: *const InternPool, dependee: Dependee) DependencyIterator { | ||
| 213 | const first_entry = switch (dependee) { | ||
| 214 | .src_hash => |x| ip.src_hash_deps.get(x), | ||
| 215 | .decl_val => |x| ip.decl_val_deps.get(x), | ||
| 216 | .namespace => |x| ip.namespace_deps.get(x), | ||
| 217 | .namespace_name => |x| ip.namespace_name_deps.get(x), | ||
| 218 | } orelse return .{ | ||
| 219 | .ip = ip, | ||
| 220 | .next_entry = .none, | ||
| 221 | }; | ||
| 222 | if (ip.dep_entries.items[@intFromEnum(first_entry)].depender == .none) return .{ | ||
| 223 | .ip = ip, | ||
| 224 | .next_entry = .none, | ||
| 225 | }; | ||
| 226 | return .{ | ||
| 227 | .ip = ip, | ||
| 228 | .next_entry = first_entry.toOptional(), | ||
| 229 | }; | ||
| 230 | } | ||
| 231 | |||
| 232 | pub fn addDependency(ip: *InternPool, gpa: Allocator, depender: Depender, dependee: Dependee) Allocator.Error!void { | ||
| 233 | const first_depender_dep: DepEntry.Index.Optional = if (ip.first_dependency.get(depender)) |idx| dep: { | ||
| 234 | // The entry already exists, so there is capacity to overwrite it later. | ||
| 235 | break :dep idx.toOptional(); | ||
| 236 | } else none: { | ||
| 237 | // Ensure there is capacity available to add this dependency later. | ||
| 238 | try ip.first_dependency.ensureUnusedCapacity(gpa, 1); | ||
| 239 | break :none .none; | ||
| 240 | }; | ||
| 241 | |||
| 242 | // We're very likely to need space for a new entry - reserve it now to avoid | ||
| 243 | // the need for error cleanup logic. | ||
| 244 | if (ip.free_dep_entries.items.len == 0) { | ||
| 245 | try ip.dep_entries.ensureUnusedCapacity(gpa, 1); | ||
| 246 | } | ||
| 247 | |||
| 248 | // This block should allocate an entry and prepend it to the relevant `*_deps` list. | ||
| 249 | // The `next` field should be correctly initialized; all other fields may be undefined. | ||
| 250 | const new_index: DepEntry.Index = switch (dependee) { | ||
| 251 | inline else => |dependee_payload, tag| new_index: { | ||
| 252 | const gop = try switch (tag) { | ||
| 253 | .src_hash => ip.src_hash_deps, | ||
| 254 | .decl_val => ip.decl_val_deps, | ||
| 255 | .namespace => ip.namespace_deps, | ||
| 256 | .namespace_name => ip.namespace_name_deps, | ||
| 257 | }.getOrPut(gpa, dependee_payload); | ||
| 258 | |||
| 259 | if (gop.found_existing and ip.dep_entries.items[@intFromEnum(gop.value_ptr.*)].depender == .none) { | ||
| 260 | // Dummy entry, so we can reuse it rather than allocating a new one! | ||
| 261 | ip.dep_entries.items[@intFromEnum(gop.value_ptr.*)].next = .none; | ||
| 262 | break :new_index gop.value_ptr.*; | ||
| 263 | } | ||
| 264 | |||
| 265 | // Prepend a new dependency. | ||
| 266 | const new_index: DepEntry.Index, const ptr = if (ip.free_dep_entries.popOrNull()) |new_index| new: { | ||
| 267 | break :new .{ new_index, &ip.dep_entries.items[@intFromEnum(new_index)] }; | ||
| 268 | } else .{ @enumFromInt(ip.dep_entries.items.len), ip.dep_entries.addOneAssumeCapacity() }; | ||
| 269 | ptr.next = if (gop.found_existing) gop.value_ptr.*.toOptional() else .none; | ||
| 270 | gop.value_ptr.* = new_index; | ||
| 271 | break :new_index new_index; | ||
| 272 | }, | ||
| 273 | }; | ||
| 274 | |||
| 275 | ip.dep_entries.items[@intFromEnum(new_index)].depender = depender.toOptional(); | ||
| 276 | ip.dep_entries.items[@intFromEnum(new_index)].prev = .none; | ||
| 277 | ip.dep_entries.items[@intFromEnum(new_index)].next_dependee = first_depender_dep; | ||
| 278 | ip.first_dependency.putAssumeCapacity(depender, new_index); | ||
| 279 | } | ||
| 280 | |||
| 281 | /// String is the name whose existence the dependency is on. | ||
| 282 | /// DepEntry.Index refers to the first such dependency. | ||
| 283 | pub const NamespaceNameKey = struct { | ||
| 284 | /// The instruction (`struct_decl` etc) which owns the namespace in question. | ||
| 285 | namespace: TrackedInst.Index, | ||
| 286 | /// The name whose existence the dependency is on. | ||
| 287 | name: NullTerminatedString, | ||
| 288 | }; | ||
| 289 | |||
| 290 | pub const DepEntry = extern struct { | ||
| 291 | /// If null, this is a dummy entry - all other fields are `undefined`. It is | ||
| 292 | /// the first and only entry in one of `intern_pool.*_deps`, and does not | ||
| 293 | /// appear in any list by `first_dependency`, but is not in | ||
| 294 | /// `free_dep_entries` since `*_deps` stores a reference to it. | ||
| 295 | depender: Depender.Optional, | ||
| 296 | /// Index into `dep_entries` forming a doubly linked list of all dependencies on this dependee. | ||
| 297 | /// Used to iterate all dependers for a given dependee during an update. | ||
| 298 | /// null if this is the end of the list. | ||
| 299 | next: DepEntry.Index.Optional, | ||
| 300 | /// The other link for `next`. | ||
| 301 | /// null if this is the start of the list. | ||
| 302 | prev: DepEntry.Index.Optional, | ||
| 303 | /// Index into `dep_entries` forming a singly linked list of dependencies *of* `depender`. | ||
| 304 | /// Used to efficiently remove all `DepEntry`s for a single `depender` when it is re-analyzed. | ||
| 305 | /// null if this is the end of the list. | ||
| 306 | next_dependee: DepEntry.Index.Optional, | ||
| 307 | |||
| 308 | pub const Index = enum(u32) { | ||
| 309 | _, | ||
| 310 | pub fn toOptional(dep: DepEntry.Index) Optional { | ||
| 311 | return @enumFromInt(@intFromEnum(dep)); | ||
| 312 | } | ||
| 313 | pub const Optional = enum(u32) { | ||
| 314 | none = std.math.maxInt(u32), | ||
| 315 | _, | ||
| 316 | pub fn unwrap(opt: Optional) ?DepEntry.Index { | ||
| 317 | return switch (opt) { | ||
| 318 | .none => null, | ||
| 319 | _ => @enumFromInt(@intFromEnum(opt)), | ||
| 320 | }; | ||
| 321 | } | ||
| 322 | }; | ||
| 323 | }; | ||
| 324 | }; | ||
| 325 | |||
| 85 | const FieldMap = std.ArrayHashMapUnmanaged(void, void, std.array_hash_map.AutoContext(void), false); | 326 | const FieldMap = std.ArrayHashMapUnmanaged(void, void, std.array_hash_map.AutoContext(void), false); |
| 86 | 327 | ||
| 87 | const builtin = @import("builtin"); | 328 | const builtin = @import("builtin"); |
| ... | @@ -428,6 +669,7 @@ pub const Key = union(enum) { | ... | @@ -428,6 +669,7 @@ pub const Key = union(enum) { |
| 428 | decl: DeclIndex, | 669 | decl: DeclIndex, |
| 429 | /// Represents the declarations inside this opaque. | 670 | /// Represents the declarations inside this opaque. |
| 430 | namespace: NamespaceIndex, | 671 | namespace: NamespaceIndex, |
| 672 | zir_index: TrackedInst.Index.Optional, | ||
| 431 | }; | 673 | }; |
| 432 | 674 | ||
| 433 | /// Although packed structs and non-packed structs are encoded differently, | 675 | /// Although packed structs and non-packed structs are encoded differently, |
| ... | @@ -440,7 +682,7 @@ pub const Key = union(enum) { | ... | @@ -440,7 +682,7 @@ pub const Key = union(enum) { |
| 440 | /// `none` when the struct has no declarations. | 682 | /// `none` when the struct has no declarations. |
| 441 | namespace: OptionalNamespaceIndex, | 683 | namespace: OptionalNamespaceIndex, |
| 442 | /// Index of the struct_decl ZIR instruction. | 684 | /// Index of the struct_decl ZIR instruction. |
| 443 | zir_index: TrackedInst.Index, | 685 | zir_index: TrackedInst.Index.Optional, |
| 444 | layout: std.builtin.Type.ContainerLayout, | 686 | layout: std.builtin.Type.ContainerLayout, |
| 445 | field_names: NullTerminatedString.Slice, | 687 | field_names: NullTerminatedString.Slice, |
| 446 | field_types: Index.Slice, | 688 | field_types: Index.Slice, |
| ... | @@ -684,7 +926,7 @@ pub const Key = union(enum) { | ... | @@ -684,7 +926,7 @@ pub const Key = union(enum) { |
| 684 | } | 926 | } |
| 685 | 927 | ||
| 686 | /// Asserts the struct is not packed. | 928 | /// Asserts the struct is not packed. |
| 687 | pub fn setZirIndex(s: @This(), ip: *InternPool, new_zir_index: TrackedInst.Index) void { | 929 | pub fn setZirIndex(s: @This(), ip: *InternPool, new_zir_index: TrackedInst.Index.Optional) void { |
| 688 | assert(s.layout != .Packed); | 930 | assert(s.layout != .Packed); |
| 689 | const field_index = std.meta.fieldIndex(Tag.TypeStruct, "zir_index").?; | 931 | const field_index = std.meta.fieldIndex(Tag.TypeStruct, "zir_index").?; |
| 690 | ip.extra.items[s.extra_index + field_index] = @intFromEnum(new_zir_index); | 932 | ip.extra.items[s.extra_index + field_index] = @intFromEnum(new_zir_index); |
| ... | @@ -800,7 +1042,7 @@ pub const Key = union(enum) { | ... | @@ -800,7 +1042,7 @@ pub const Key = union(enum) { |
| 800 | flags: Tag.TypeUnion.Flags, | 1042 | flags: Tag.TypeUnion.Flags, |
| 801 | /// The enum that provides the list of field names and values. | 1043 | /// The enum that provides the list of field names and values. |
| 802 | enum_tag_ty: Index, | 1044 | enum_tag_ty: Index, |
| 803 | zir_index: TrackedInst.Index, | 1045 | zir_index: TrackedInst.Index.Optional, |
| 804 | 1046 | ||
| 805 | /// The returned pointer expires with any addition to the `InternPool`. | 1047 | /// The returned pointer expires with any addition to the `InternPool`. |
| 806 | pub fn flagsPtr(self: @This(), ip: *const InternPool) *Tag.TypeUnion.Flags { | 1048 | pub fn flagsPtr(self: @This(), ip: *const InternPool) *Tag.TypeUnion.Flags { |
| ... | @@ -889,6 +1131,7 @@ pub const Key = union(enum) { | ... | @@ -889,6 +1131,7 @@ pub const Key = union(enum) { |
| 889 | /// This is ignored by `get` but will be provided by `indexToKey` when | 1131 | /// This is ignored by `get` but will be provided by `indexToKey` when |
| 890 | /// a value map exists. | 1132 | /// a value map exists. |
| 891 | values_map: OptionalMapIndex = .none, | 1133 | values_map: OptionalMapIndex = .none, |
| 1134 | zir_index: TrackedInst.Index.Optional, | ||
| 892 | 1135 | ||
| 893 | pub const TagMode = enum { | 1136 | pub const TagMode = enum { |
| 894 | /// The integer tag type was auto-numbered by zig. | 1137 | /// The integer tag type was auto-numbered by zig. |
| ... | @@ -953,6 +1196,7 @@ pub const Key = union(enum) { | ... | @@ -953,6 +1196,7 @@ pub const Key = union(enum) { |
| 953 | tag_mode: EnumType.TagMode, | 1196 | tag_mode: EnumType.TagMode, |
| 954 | /// This may be updated via `setTagType` later. | 1197 | /// This may be updated via `setTagType` later. |
| 955 | tag_ty: Index = .none, | 1198 | tag_ty: Index = .none, |
| 1199 | zir_index: TrackedInst.Index.Optional, | ||
| 956 | 1200 | ||
| 957 | pub fn toEnumType(self: @This()) EnumType { | 1201 | pub fn toEnumType(self: @This()) EnumType { |
| 958 | return .{ | 1202 | return .{ |
| ... | @@ -962,6 +1206,7 @@ pub const Key = union(enum) { | ... | @@ -962,6 +1206,7 @@ pub const Key = union(enum) { |
| 962 | .tag_mode = self.tag_mode, | 1206 | .tag_mode = self.tag_mode, |
| 963 | .names = .{ .start = 0, .len = 0 }, | 1207 | .names = .{ .start = 0, .len = 0 }, |
| 964 | .values = .{ .start = 0, .len = 0 }, | 1208 | .values = .{ .start = 0, .len = 0 }, |
| 1209 | .zir_index = self.zir_index, | ||
| 965 | }; | 1210 | }; |
| 966 | } | 1211 | } |
| 967 | 1212 | ||
| ... | @@ -1909,7 +2154,7 @@ pub const UnionType = struct { | ... | @@ -1909,7 +2154,7 @@ pub const UnionType = struct { |
| 1909 | /// If this slice has length 0 it means all elements are `none`. | 2154 | /// If this slice has length 0 it means all elements are `none`. |
| 1910 | field_aligns: Alignment.Slice, | 2155 | field_aligns: Alignment.Slice, |
| 1911 | /// Index of the union_decl ZIR instruction. | 2156 | /// Index of the union_decl ZIR instruction. |
| 1912 | zir_index: TrackedInst.Index, | 2157 | zir_index: TrackedInst.Index.Optional, |
| 1913 | /// Index into extra array of the `flags` field. | 2158 | /// Index into extra array of the `flags` field. |
| 1914 | flags_index: u32, | 2159 | flags_index: u32, |
| 1915 | /// Copied from `enum_tag_ty`. | 2160 | /// Copied from `enum_tag_ty`. |
| ... | @@ -2003,10 +2248,10 @@ pub const UnionType = struct { | ... | @@ -2003,10 +2248,10 @@ pub const UnionType = struct { |
| 2003 | } | 2248 | } |
| 2004 | 2249 | ||
| 2005 | /// This does not mutate the field of UnionType. | 2250 | /// This does not mutate the field of UnionType. |
| 2006 | pub fn setZirIndex(self: @This(), ip: *InternPool, new_zir_index: TrackedInst.Index) void { | 2251 | pub fn setZirIndex(self: @This(), ip: *InternPool, new_zir_index: TrackedInst.Index.Optional) void { |
| 2007 | const flags_field_index = std.meta.fieldIndex(Tag.TypeUnion, "flags").?; | 2252 | const flags_field_index = std.meta.fieldIndex(Tag.TypeUnion, "flags").?; |
| 2008 | const zir_index_field_index = std.meta.fieldIndex(Tag.TypeUnion, "zir_index").?; | 2253 | const zir_index_field_index = std.meta.fieldIndex(Tag.TypeUnion, "zir_index").?; |
| 2009 | const ptr: *TrackedInst.Index = | 2254 | const ptr: *TrackedInst.Index.Optional = |
| 2010 | @ptrCast(&ip.extra.items[self.flags_index - flags_field_index + zir_index_field_index]); | 2255 | @ptrCast(&ip.extra.items[self.flags_index - flags_field_index + zir_index_field_index]); |
| 2011 | ptr.* = new_zir_index; | 2256 | ptr.* = new_zir_index; |
| 2012 | } | 2257 | } |
| ... | @@ -3099,7 +3344,7 @@ pub const Tag = enum(u8) { | ... | @@ -3099,7 +3344,7 @@ pub const Tag = enum(u8) { |
| 3099 | namespace: NamespaceIndex, | 3344 | namespace: NamespaceIndex, |
| 3100 | /// The enum that provides the list of field names and values. | 3345 | /// The enum that provides the list of field names and values. |
| 3101 | tag_ty: Index, | 3346 | tag_ty: Index, |
| 3102 | zir_index: TrackedInst.Index, | 3347 | zir_index: TrackedInst.Index.Optional, |
| 3103 | 3348 | ||
| 3104 | pub const Flags = packed struct(u32) { | 3349 | pub const Flags = packed struct(u32) { |
| 3105 | runtime_tag: UnionType.RuntimeTag, | 3350 | runtime_tag: UnionType.RuntimeTag, |
| ... | @@ -3121,7 +3366,7 @@ pub const Tag = enum(u8) { | ... | @@ -3121,7 +3366,7 @@ pub const Tag = enum(u8) { |
| 3121 | /// 2. init: Index for each fields_len // if tag is type_struct_packed_inits | 3366 | /// 2. init: Index for each fields_len // if tag is type_struct_packed_inits |
| 3122 | pub const TypeStructPacked = struct { | 3367 | pub const TypeStructPacked = struct { |
| 3123 | decl: DeclIndex, | 3368 | decl: DeclIndex, |
| 3124 | zir_index: TrackedInst.Index, | 3369 | zir_index: TrackedInst.Index.Optional, |
| 3125 | fields_len: u32, | 3370 | fields_len: u32, |
| 3126 | namespace: OptionalNamespaceIndex, | 3371 | namespace: OptionalNamespaceIndex, |
| 3127 | backing_int_ty: Index, | 3372 | backing_int_ty: Index, |
| ... | @@ -3168,7 +3413,7 @@ pub const Tag = enum(u8) { | ... | @@ -3168,7 +3413,7 @@ pub const Tag = enum(u8) { |
| 3168 | /// 7. field_offset: u32 // for each field in declared order, undef until layout_resolved | 3413 | /// 7. field_offset: u32 // for each field in declared order, undef until layout_resolved |
| 3169 | pub const TypeStruct = struct { | 3414 | pub const TypeStruct = struct { |
| 3170 | decl: DeclIndex, | 3415 | decl: DeclIndex, |
| 3171 | zir_index: TrackedInst.Index, | 3416 | zir_index: TrackedInst.Index.Optional, |
| 3172 | fields_len: u32, | 3417 | fields_len: u32, |
| 3173 | flags: Flags, | 3418 | flags: Flags, |
| 3174 | size: u32, | 3419 | size: u32, |
| ... | @@ -3238,6 +3483,11 @@ pub const FuncAnalysis = packed struct(u32) { | ... | @@ -3238,6 +3483,11 @@ pub const FuncAnalysis = packed struct(u32) { |
| 3238 | /// This function might be OK but it depends on another Decl which did not | 3483 | /// This function might be OK but it depends on another Decl which did not |
| 3239 | /// successfully complete semantic analysis. | 3484 | /// successfully complete semantic analysis. |
| 3240 | dependency_failure, | 3485 | dependency_failure, |
| 3486 | /// There will be a corresponding ErrorMsg in Module.failed_decls. | ||
| 3487 | /// Indicates that semantic analysis succeeded, but code generation for | ||
| 3488 | /// this function failed. | ||
| 3489 | codegen_failure, | ||
| 3490 | /// Semantic analysis and code generation of this function succeeded. | ||
| 3241 | success, | 3491 | success, |
| 3242 | }; | 3492 | }; |
| 3243 | }; | 3493 | }; |
| ... | @@ -3523,6 +3773,7 @@ pub const EnumExplicit = struct { | ... | @@ -3523,6 +3773,7 @@ pub const EnumExplicit = struct { |
| 3523 | /// If this is `none`, it means the trailing tag values are absent because | 3773 | /// If this is `none`, it means the trailing tag values are absent because |
| 3524 | /// they are auto-numbered. | 3774 | /// they are auto-numbered. |
| 3525 | values_map: OptionalMapIndex, | 3775 | values_map: OptionalMapIndex, |
| 3776 | zir_index: TrackedInst.Index.Optional, | ||
| 3526 | }; | 3777 | }; |
| 3527 | 3778 | ||
| 3528 | /// Trailing: | 3779 | /// Trailing: |
| ... | @@ -3538,6 +3789,7 @@ pub const EnumAuto = struct { | ... | @@ -3538,6 +3789,7 @@ pub const EnumAuto = struct { |
| 3538 | fields_len: u32, | 3789 | fields_len: u32, |
| 3539 | /// Maps field names to declaration index. | 3790 | /// Maps field names to declaration index. |
| 3540 | names_map: MapIndex, | 3791 | names_map: MapIndex, |
| 3792 | zir_index: TrackedInst.Index.Optional, | ||
| 3541 | }; | 3793 | }; |
| 3542 | 3794 | ||
| 3543 | pub const PackedU64 = packed struct(u64) { | 3795 | pub const PackedU64 = packed struct(u64) { |
| ... | @@ -3759,6 +4011,16 @@ pub fn deinit(ip: *InternPool, gpa: Allocator) void { | ... | @@ -3759,6 +4011,16 @@ pub fn deinit(ip: *InternPool, gpa: Allocator) void { |
| 3759 | 4011 | ||
| 3760 | ip.tracked_insts.deinit(gpa); | 4012 | ip.tracked_insts.deinit(gpa); |
| 3761 | 4013 | ||
| 4014 | ip.src_hash_deps.deinit(gpa); | ||
| 4015 | ip.decl_val_deps.deinit(gpa); | ||
| 4016 | ip.namespace_deps.deinit(gpa); | ||
| 4017 | ip.namespace_name_deps.deinit(gpa); | ||
| 4018 | |||
| 4019 | ip.first_dependency.deinit(gpa); | ||
| 4020 | |||
| 4021 | ip.dep_entries.deinit(gpa); | ||
| 4022 | ip.free_dep_entries.deinit(gpa); | ||
| 4023 | |||
| 3762 | ip.* = undefined; | 4024 | ip.* = undefined; |
| 3763 | } | 4025 | } |
| 3764 | 4026 | ||
| ... | @@ -3885,6 +4147,7 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { | ... | @@ -3885,6 +4147,7 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { |
| 3885 | .tag_mode = .auto, | 4147 | .tag_mode = .auto, |
| 3886 | .names_map = enum_auto.data.names_map.toOptional(), | 4148 | .names_map = enum_auto.data.names_map.toOptional(), |
| 3887 | .values_map = .none, | 4149 | .values_map = .none, |
| 4150 | .zir_index = enum_auto.data.zir_index, | ||
| 3888 | } }; | 4151 | } }; |
| 3889 | }, | 4152 | }, |
| 3890 | .type_enum_explicit => ip.indexToKeyEnum(data, .explicit), | 4153 | .type_enum_explicit => ip.indexToKeyEnum(data, .explicit), |
| ... | @@ -4493,6 +4756,7 @@ fn indexToKeyEnum(ip: *const InternPool, data: u32, tag_mode: Key.EnumType.TagMo | ... | @@ -4493,6 +4756,7 @@ fn indexToKeyEnum(ip: *const InternPool, data: u32, tag_mode: Key.EnumType.TagMo |
| 4493 | .tag_mode = tag_mode, | 4756 | .tag_mode = tag_mode, |
| 4494 | .names_map = enum_explicit.data.names_map.toOptional(), | 4757 | .names_map = enum_explicit.data.names_map.toOptional(), |
| 4495 | .values_map = enum_explicit.data.values_map, | 4758 | .values_map = enum_explicit.data.values_map, |
| 4759 | .zir_index = enum_explicit.data.zir_index, | ||
| 4496 | } }; | 4760 | } }; |
| 4497 | } | 4761 | } |
| 4498 | 4762 | ||
| ... | @@ -5329,7 +5593,7 @@ pub const UnionTypeInit = struct { | ... | @@ -5329,7 +5593,7 @@ pub const UnionTypeInit = struct { |
| 5329 | flags: Tag.TypeUnion.Flags, | 5593 | flags: Tag.TypeUnion.Flags, |
| 5330 | decl: DeclIndex, | 5594 | decl: DeclIndex, |
| 5331 | namespace: NamespaceIndex, | 5595 | namespace: NamespaceIndex, |
| 5332 | zir_index: TrackedInst.Index, | 5596 | zir_index: TrackedInst.Index.Optional, |
| 5333 | fields_len: u32, | 5597 | fields_len: u32, |
| 5334 | enum_tag_ty: Index, | 5598 | enum_tag_ty: Index, |
| 5335 | /// May have length 0 which leaves the values unset until later. | 5599 | /// May have length 0 which leaves the values unset until later. |
| ... | @@ -5401,7 +5665,7 @@ pub const StructTypeInit = struct { | ... | @@ -5401,7 +5665,7 @@ pub const StructTypeInit = struct { |
| 5401 | decl: DeclIndex, | 5665 | decl: DeclIndex, |
| 5402 | namespace: OptionalNamespaceIndex, | 5666 | namespace: OptionalNamespaceIndex, |
| 5403 | layout: std.builtin.Type.ContainerLayout, | 5667 | layout: std.builtin.Type.ContainerLayout, |
| 5404 | zir_index: TrackedInst.Index, | 5668 | zir_index: TrackedInst.Index.Optional, |
| 5405 | fields_len: u32, | 5669 | fields_len: u32, |
| 5406 | known_non_opv: bool, | 5670 | known_non_opv: bool, |
| 5407 | requires_comptime: RequiresComptime, | 5671 | requires_comptime: RequiresComptime, |
| ... | @@ -5923,7 +6187,6 @@ pub const GetFuncInstanceKey = struct { | ... | @@ -5923,7 +6187,6 @@ pub const GetFuncInstanceKey = struct { |
| 5923 | is_noinline: bool, | 6187 | is_noinline: bool, |
| 5924 | generic_owner: Index, | 6188 | generic_owner: Index, |
| 5925 | inferred_error_set: bool, | 6189 | inferred_error_set: bool, |
| 5926 | generation: u32, | ||
| 5927 | }; | 6190 | }; |
| 5928 | 6191 | ||
| 5929 | pub fn getFuncInstance(ip: *InternPool, gpa: Allocator, arg: GetFuncInstanceKey) Allocator.Error!Index { | 6192 | pub fn getFuncInstance(ip: *InternPool, gpa: Allocator, arg: GetFuncInstanceKey) Allocator.Error!Index { |
| ... | @@ -5990,7 +6253,6 @@ pub fn getFuncInstance(ip: *InternPool, gpa: Allocator, arg: GetFuncInstanceKey) | ... | @@ -5990,7 +6253,6 @@ pub fn getFuncInstance(ip: *InternPool, gpa: Allocator, arg: GetFuncInstanceKey) |
| 5990 | generic_owner, | 6253 | generic_owner, |
| 5991 | func_index, | 6254 | func_index, |
| 5992 | func_extra_index, | 6255 | func_extra_index, |
| 5993 | arg.generation, | ||
| 5994 | func_ty, | 6256 | func_ty, |
| 5995 | arg.section, | 6257 | arg.section, |
| 5996 | ); | 6258 | ); |
| ... | @@ -6122,7 +6384,6 @@ pub fn getFuncInstanceIes( | ... | @@ -6122,7 +6384,6 @@ pub fn getFuncInstanceIes( |
| 6122 | generic_owner, | 6384 | generic_owner, |
| 6123 | func_index, | 6385 | func_index, |
| 6124 | func_extra_index, | 6386 | func_extra_index, |
| 6125 | arg.generation, | ||
| 6126 | func_ty, | 6387 | func_ty, |
| 6127 | arg.section, | 6388 | arg.section, |
| 6128 | ); | 6389 | ); |
| ... | @@ -6134,7 +6395,6 @@ fn finishFuncInstance( | ... | @@ -6134,7 +6395,6 @@ fn finishFuncInstance( |
| 6134 | generic_owner: Index, | 6395 | generic_owner: Index, |
| 6135 | func_index: Index, | 6396 | func_index: Index, |
| 6136 | func_extra_index: u32, | 6397 | func_extra_index: u32, |
| 6137 | generation: u32, | ||
| 6138 | func_ty: Index, | 6398 | func_ty: Index, |
| 6139 | section: OptionalNullTerminatedString, | 6399 | section: OptionalNullTerminatedString, |
| 6140 | ) Allocator.Error!Index { | 6400 | ) Allocator.Error!Index { |
| ... | @@ -6154,7 +6414,6 @@ fn finishFuncInstance( | ... | @@ -6154,7 +6414,6 @@ fn finishFuncInstance( |
| 6154 | .analysis = .complete, | 6414 | .analysis = .complete, |
| 6155 | .zir_decl_index = fn_owner_decl.zir_decl_index, | 6415 | .zir_decl_index = fn_owner_decl.zir_decl_index, |
| 6156 | .src_scope = fn_owner_decl.src_scope, | 6416 | .src_scope = fn_owner_decl.src_scope, |
| 6157 | .generation = generation, | ||
| 6158 | .is_pub = fn_owner_decl.is_pub, | 6417 | .is_pub = fn_owner_decl.is_pub, |
| 6159 | .is_exported = fn_owner_decl.is_exported, | 6418 | .is_exported = fn_owner_decl.is_exported, |
| 6160 | .alive = true, | 6419 | .alive = true, |
| ... | @@ -6264,6 +6523,7 @@ fn getIncompleteEnumAuto( | ... | @@ -6264,6 +6523,7 @@ fn getIncompleteEnumAuto( |
| 6264 | .int_tag_type = int_tag_type, | 6523 | .int_tag_type = int_tag_type, |
| 6265 | .names_map = names_map, | 6524 | .names_map = names_map, |
| 6266 | .fields_len = enum_type.fields_len, | 6525 | .fields_len = enum_type.fields_len, |
| 6526 | .zir_index = enum_type.zir_index, | ||
| 6267 | }); | 6527 | }); |
| 6268 | 6528 | ||
| 6269 | ip.items.appendAssumeCapacity(.{ | 6529 | ip.items.appendAssumeCapacity(.{ |
| ... | @@ -6314,6 +6574,7 @@ fn getIncompleteEnumExplicit( | ... | @@ -6314,6 +6574,7 @@ fn getIncompleteEnumExplicit( |
| 6314 | .fields_len = enum_type.fields_len, | 6574 | .fields_len = enum_type.fields_len, |
| 6315 | .names_map = names_map, | 6575 | .names_map = names_map, |
| 6316 | .values_map = values_map, | 6576 | .values_map = values_map, |
| 6577 | .zir_index = enum_type.zir_index, | ||
| 6317 | }); | 6578 | }); |
| 6318 | 6579 | ||
| 6319 | ip.items.appendAssumeCapacity(.{ | 6580 | ip.items.appendAssumeCapacity(.{ |
| ... | @@ -6339,6 +6600,7 @@ pub const GetEnumInit = struct { | ... | @@ -6339,6 +6600,7 @@ pub const GetEnumInit = struct { |
| 6339 | names: []const NullTerminatedString, | 6600 | names: []const NullTerminatedString, |
| 6340 | values: []const Index, | 6601 | values: []const Index, |
| 6341 | tag_mode: Key.EnumType.TagMode, | 6602 | tag_mode: Key.EnumType.TagMode, |
| 6603 | zir_index: TrackedInst.Index.Optional, | ||
| 6342 | }; | 6604 | }; |
| 6343 | 6605 | ||
| 6344 | pub fn getEnum(ip: *InternPool, gpa: Allocator, ini: GetEnumInit) Allocator.Error!Index { | 6606 | pub fn getEnum(ip: *InternPool, gpa: Allocator, ini: GetEnumInit) Allocator.Error!Index { |
| ... | @@ -6355,6 +6617,7 @@ pub fn getEnum(ip: *InternPool, gpa: Allocator, ini: GetEnumInit) Allocator.Erro | ... | @@ -6355,6 +6617,7 @@ pub fn getEnum(ip: *InternPool, gpa: Allocator, ini: GetEnumInit) Allocator.Erro |
| 6355 | .tag_mode = undefined, | 6617 | .tag_mode = undefined, |
| 6356 | .names_map = undefined, | 6618 | .names_map = undefined, |
| 6357 | .values_map = undefined, | 6619 | .values_map = undefined, |
| 6620 | .zir_index = undefined, | ||
| 6358 | }, | 6621 | }, |
| 6359 | }, adapter); | 6622 | }, adapter); |
| 6360 | if (gop.found_existing) return @enumFromInt(gop.index); | 6623 | if (gop.found_existing) return @enumFromInt(gop.index); |
| ... | @@ -6380,6 +6643,7 @@ pub fn getEnum(ip: *InternPool, gpa: Allocator, ini: GetEnumInit) Allocator.Erro | ... | @@ -6380,6 +6643,7 @@ pub fn getEnum(ip: *InternPool, gpa: Allocator, ini: GetEnumInit) Allocator.Erro |
| 6380 | .int_tag_type = ini.tag_ty, | 6643 | .int_tag_type = ini.tag_ty, |
| 6381 | .names_map = names_map, | 6644 | .names_map = names_map, |
| 6382 | .fields_len = fields_len, | 6645 | .fields_len = fields_len, |
| 6646 | .zir_index = ini.zir_index, | ||
| 6383 | }), | 6647 | }), |
| 6384 | }); | 6648 | }); |
| 6385 | ip.extra.appendSliceAssumeCapacity(@ptrCast(ini.names)); | 6649 | ip.extra.appendSliceAssumeCapacity(@ptrCast(ini.names)); |
| ... | @@ -6416,6 +6680,7 @@ pub fn finishGetEnum( | ... | @@ -6416,6 +6680,7 @@ pub fn finishGetEnum( |
| 6416 | .fields_len = fields_len, | 6680 | .fields_len = fields_len, |
| 6417 | .names_map = names_map, | 6681 | .names_map = names_map, |
| 6418 | .values_map = values_map, | 6682 | .values_map = values_map, |
| 6683 | .zir_index = ini.zir_index, | ||
| 6419 | }), | 6684 | }), |
| 6420 | }); | 6685 | }); |
| 6421 | ip.extra.appendSliceAssumeCapacity(@ptrCast(ini.names)); | 6686 | ip.extra.appendSliceAssumeCapacity(@ptrCast(ini.names)); |
| ... | @@ -6507,6 +6772,7 @@ fn addExtraAssumeCapacity(ip: *InternPool, extra: anytype) u32 { | ... | @@ -6507,6 +6772,7 @@ fn addExtraAssumeCapacity(ip: *InternPool, extra: anytype) u32 { |
| 6507 | OptionalNullTerminatedString, | 6772 | OptionalNullTerminatedString, |
| 6508 | Tag.TypePointer.VectorIndex, | 6773 | Tag.TypePointer.VectorIndex, |
| 6509 | TrackedInst.Index, | 6774 | TrackedInst.Index, |
| 6775 | TrackedInst.Index.Optional, | ||
| 6510 | => @intFromEnum(@field(extra, field.name)), | 6776 | => @intFromEnum(@field(extra, field.name)), |
| 6511 | 6777 | ||
| 6512 | u32, | 6778 | u32, |
| ... | @@ -6583,6 +6849,7 @@ fn extraDataTrail(ip: *const InternPool, comptime T: type, index: usize) struct | ... | @@ -6583,6 +6849,7 @@ fn extraDataTrail(ip: *const InternPool, comptime T: type, index: usize) struct |
| 6583 | OptionalNullTerminatedString, | 6849 | OptionalNullTerminatedString, |
| 6584 | Tag.TypePointer.VectorIndex, | 6850 | Tag.TypePointer.VectorIndex, |
| 6585 | TrackedInst.Index, | 6851 | TrackedInst.Index, |
| 6852 | TrackedInst.Index.Optional, | ||
| 6586 | => @enumFromInt(int32), | 6853 | => @enumFromInt(int32), |
| 6587 | 6854 | ||
| 6588 | u32, | 6855 | u32, |
src/Module.zig+606-222| ... | @@ -144,10 +144,26 @@ global_error_set: GlobalErrorSet = .{}, | ... | @@ -144,10 +144,26 @@ global_error_set: GlobalErrorSet = .{}, |
| 144 | /// Maximum amount of distinct error values, set by --error-limit | 144 | /// Maximum amount of distinct error values, set by --error-limit |
| 145 | error_limit: ErrorInt, | 145 | error_limit: ErrorInt, |
| 146 | 146 | ||
| 147 | /// Incrementing integer used to compare against the corresponding Decl | 147 | /// Value is the number of PO or outdated Decls which this Depender depends on. |
| 148 | /// field to determine whether a Decl's status applies to an ongoing update, or a | 148 | potentially_outdated: std.AutoArrayHashMapUnmanaged(InternPool.Depender, u32) = .{}, |
| 149 | /// previous analysis. | 149 | /// Value is the number of PO or outdated Decls which this Depender depends on. |
| 150 | generation: u32 = 0, | 150 | /// Once this value drops to 0, the Depender is a candidate for re-analysis. |
| 151 | outdated: std.AutoArrayHashMapUnmanaged(InternPool.Depender, u32) = .{}, | ||
| 152 | /// This contains all `Depender`s in `outdated` whose PO dependency count is 0. | ||
| 153 | /// Such `Depender`s are ready for immediate re-analysis. | ||
| 154 | /// See `findOutdatedToAnalyze` for details. | ||
| 155 | outdated_ready: std.AutoArrayHashMapUnmanaged(InternPool.Depender, void) = .{}, | ||
| 156 | /// This contains a set of Decls which may not be in `outdated`, but are the | ||
| 157 | /// root Decls of files which have updated source and thus must be re-analyzed. | ||
| 158 | /// If such a Decl is only in this set, the struct type index may be preserved | ||
| 159 | /// (only the namespace might change). If such a Decl is also `outdated`, the | ||
| 160 | /// struct type index must be recreated. | ||
| 161 | outdated_file_root: std.AutoArrayHashMapUnmanaged(Decl.Index, void) = .{}, | ||
| 162 | /// This contains a list of Dependers whose analysis or codegen failed, but the | ||
| 163 | /// failure was something like running out of disk space, and trying again may | ||
| 164 | /// succeed. On the next update, we will flush this list, marking all members of | ||
| 165 | /// it as outdated. | ||
| 166 | retryable_failures: std.ArrayListUnmanaged(InternPool.Depender) = .{}, | ||
| 151 | 167 | ||
| 152 | stage1_flags: packed struct { | 168 | stage1_flags: packed struct { |
| 153 | have_winmain: bool = false, | 169 | have_winmain: bool = false, |
| ... | @@ -364,21 +380,14 @@ pub const Decl = struct { | ... | @@ -364,21 +380,14 @@ pub const Decl = struct { |
| 364 | alignment: Alignment, | 380 | alignment: Alignment, |
| 365 | /// Populated when `has_tv`. | 381 | /// Populated when `has_tv`. |
| 366 | @"addrspace": std.builtin.AddressSpace, | 382 | @"addrspace": std.builtin.AddressSpace, |
| 367 | /// The direct parent namespace of the Decl. | 383 | /// The direct parent namespace of the Decl. In the case of the Decl |
| 368 | /// Reference to externally owned memory. | 384 | /// corresponding to a file, this is the namespace of the struct, since |
| 369 | /// In the case of the Decl corresponding to a file, this is | 385 | /// there is no parent. |
| 370 | /// the namespace of the struct, since there is no parent. | ||
| 371 | src_namespace: Namespace.Index, | 386 | src_namespace: Namespace.Index, |
| 372 | 387 | ||
| 373 | /// The scope which lexically contains this decl. A decl must depend | 388 | /// The scope which lexically contains this decl. |
| 374 | /// on its lexical parent, in order to ensure that this pointer is valid. | ||
| 375 | /// This scope is allocated out of the arena of the parent decl. | ||
| 376 | src_scope: CaptureScope.Index, | 389 | src_scope: CaptureScope.Index, |
| 377 | 390 | ||
| 378 | /// An integer that can be checked against the corresponding incrementing | ||
| 379 | /// generation field of Module. This is used to determine whether `complete` status | ||
| 380 | /// represents pre- or post- re-analysis. | ||
| 381 | generation: u32, | ||
| 382 | /// The AST node index of this declaration. | 391 | /// The AST node index of this declaration. |
| 383 | /// Must be recomputed when the corresponding source file is modified. | 392 | /// Must be recomputed when the corresponding source file is modified. |
| 384 | src_node: Ast.Node.Index, | 393 | src_node: Ast.Node.Index, |
| ... | @@ -404,31 +413,20 @@ pub const Decl = struct { | ... | @@ -404,31 +413,20 @@ pub const Decl = struct { |
| 404 | /// The file corresponding to this Decl had a parse error or ZIR error. | 413 | /// The file corresponding to this Decl had a parse error or ZIR error. |
| 405 | /// There will be a corresponding ErrorMsg in Module.failed_files. | 414 | /// There will be a corresponding ErrorMsg in Module.failed_files. |
| 406 | file_failure, | 415 | file_failure, |
| 407 | /// This Decl might be OK but it depends on another one which did not successfully complete | 416 | /// This Decl might be OK but it depends on another one which did not |
| 408 | /// semantic analysis. | 417 | /// successfully complete semantic analysis. |
| 409 | dependency_failure, | 418 | dependency_failure, |
| 410 | /// Semantic analysis failure. | 419 | /// Semantic analysis failure. |
| 411 | /// There will be a corresponding ErrorMsg in Module.failed_decls. | 420 | /// There will be a corresponding ErrorMsg in Module.failed_decls. |
| 412 | sema_failure, | 421 | sema_failure, |
| 413 | /// There will be a corresponding ErrorMsg in Module.failed_decls. | 422 | /// There will be a corresponding ErrorMsg in Module.failed_decls. |
| 414 | /// This indicates the failure was something like running out of disk space, | ||
| 415 | /// and attempting semantic analysis again may succeed. | ||
| 416 | sema_failure_retryable, | ||
| 417 | /// There will be a corresponding ErrorMsg in Module.failed_decls. | ||
| 418 | liveness_failure, | ||
| 419 | /// There will be a corresponding ErrorMsg in Module.failed_decls. | ||
| 420 | codegen_failure, | 423 | codegen_failure, |
| 421 | /// There will be a corresponding ErrorMsg in Module.failed_decls. | 424 | /// Sematic analysis and constant value codegen of this Decl has |
| 422 | /// This indicates the failure was something like running out of disk space, | 425 | /// succeeded. However, the Decl may be outdated due to an in-progress |
| 423 | /// and attempting codegen again may succeed. | 426 | /// update. Note that for a function, this does not mean codegen of the |
| 424 | codegen_failure_retryable, | 427 | /// function body succeded: that state is indicated by the function's |
| 425 | /// Everything is done. During an update, this Decl may be out of date, depending | 428 | /// `analysis` field. |
| 426 | /// on its dependencies. The `generation` field can be used to determine if this | ||
| 427 | /// completion status occurred before or after a given update. | ||
| 428 | complete, | 429 | complete, |
| 429 | /// A Module update is in progress, and this Decl has been flagged as being known | ||
| 430 | /// to require re-analysis. | ||
| 431 | outdated, | ||
| 432 | }, | 430 | }, |
| 433 | /// Whether `typed_value`, `align`, `linksection` and `addrspace` are populated. | 431 | /// Whether `typed_value`, `align`, `linksection` and `addrspace` are populated. |
| 434 | has_tv: bool, | 432 | has_tv: bool, |
| ... | @@ -680,14 +678,6 @@ pub const Decl = struct { | ... | @@ -680,14 +678,6 @@ pub const Decl = struct { |
| 680 | return mod.namespacePtr(decl.src_namespace).file_scope; | 678 | return mod.namespacePtr(decl.src_namespace).file_scope; |
| 681 | } | 679 | } |
| 682 | 680 | ||
| 683 | pub fn removeDependant(decl: *Decl, other: Decl.Index) void { | ||
| 684 | assert(decl.dependants.swapRemove(other)); | ||
| 685 | } | ||
| 686 | |||
| 687 | pub fn removeDependency(decl: *Decl, other: Decl.Index) void { | ||
| 688 | assert(decl.dependencies.swapRemove(other)); | ||
| 689 | } | ||
| 690 | |||
| 691 | pub fn getExternDecl(decl: Decl, mod: *Module) OptionalIndex { | 681 | pub fn getExternDecl(decl: Decl, mod: *Module) OptionalIndex { |
| 692 | assert(decl.has_tv); | 682 | assert(decl.has_tv); |
| 693 | return switch (mod.intern_pool.indexToKey(decl.val.toIntern())) { | 683 | return switch (mod.intern_pool.indexToKey(decl.val.toIntern())) { |
| ... | @@ -734,8 +724,7 @@ pub const Namespace = struct { | ... | @@ -734,8 +724,7 @@ pub const Namespace = struct { |
| 734 | file_scope: *File, | 724 | file_scope: *File, |
| 735 | /// Will be a struct, enum, union, or opaque. | 725 | /// Will be a struct, enum, union, or opaque. |
| 736 | ty: Type, | 726 | ty: Type, |
| 737 | /// Direct children of the namespace. Used during an update to detect | 727 | /// Direct children of the namespace. |
| 738 | /// which decls have been added/removed from source. | ||
| 739 | /// Declaration order is preserved via entry order. | 728 | /// Declaration order is preserved via entry order. |
| 740 | /// These are only declarations named directly by the AST; anonymous | 729 | /// These are only declarations named directly by the AST; anonymous |
| 741 | /// declarations are not stored here. | 730 | /// declarations are not stored here. |
| ... | @@ -838,14 +827,6 @@ pub const File = struct { | ... | @@ -838,14 +827,6 @@ pub const File = struct { |
| 838 | /// undefined until `zir_loaded == true`. | 827 | /// undefined until `zir_loaded == true`. |
| 839 | path_digest: Cache.BinDigest = undefined, | 828 | path_digest: Cache.BinDigest = undefined, |
| 840 | 829 | ||
| 841 | /// Used by change detection algorithm, after astgen, contains the | ||
| 842 | /// set of decls that existed in the previous ZIR but not in the new one. | ||
| 843 | deleted_decls: ArrayListUnmanaged(Decl.Index) = .{}, | ||
| 844 | /// Used by change detection algorithm, after astgen, contains the | ||
| 845 | /// set of decls that existed both in the previous ZIR and in the new one, | ||
| 846 | /// but their source code has been modified. | ||
| 847 | outdated_decls: ArrayListUnmanaged(Decl.Index) = .{}, | ||
| 848 | |||
| 849 | /// The most recent successful ZIR for this file, with no errors. | 830 | /// The most recent successful ZIR for this file, with no errors. |
| 850 | /// This is only populated when a previously successful ZIR | 831 | /// This is only populated when a previously successful ZIR |
| 851 | /// newly introduces compile errors during an update. When ZIR is | 832 | /// newly introduces compile errors during an update. When ZIR is |
| ... | @@ -898,8 +879,6 @@ pub const File = struct { | ... | @@ -898,8 +879,6 @@ pub const File = struct { |
| 898 | gpa.free(file.sub_file_path); | 879 | gpa.free(file.sub_file_path); |
| 899 | file.unload(gpa); | 880 | file.unload(gpa); |
| 900 | } | 881 | } |
| 901 | file.deleted_decls.deinit(gpa); | ||
| 902 | file.outdated_decls.deinit(gpa); | ||
| 903 | file.references.deinit(gpa); | 882 | file.references.deinit(gpa); |
| 904 | if (file.root_decl.unwrap()) |root_decl| { | 883 | if (file.root_decl.unwrap()) |root_decl| { |
| 905 | mod.destroyDecl(root_decl); | 884 | mod.destroyDecl(root_decl); |
| ... | @@ -2498,6 +2477,12 @@ pub fn deinit(zcu: *Zcu) void { | ... | @@ -2498,6 +2477,12 @@ pub fn deinit(zcu: *Zcu) void { |
| 2498 | 2477 | ||
| 2499 | zcu.global_error_set.deinit(gpa); | 2478 | zcu.global_error_set.deinit(gpa); |
| 2500 | 2479 | ||
| 2480 | zcu.potentially_outdated.deinit(gpa); | ||
| 2481 | zcu.outdated.deinit(gpa); | ||
| 2482 | zcu.outdated_ready.deinit(gpa); | ||
| 2483 | zcu.outdated_file_root.deinit(gpa); | ||
| 2484 | zcu.retryable_failures.deinit(gpa); | ||
| 2485 | |||
| 2501 | zcu.test_functions.deinit(gpa); | 2486 | zcu.test_functions.deinit(gpa); |
| 2502 | 2487 | ||
| 2503 | for (zcu.global_assembly.values()) |s| { | 2488 | for (zcu.global_assembly.values()) |s| { |
| ... | @@ -2856,27 +2841,20 @@ pub fn astGenFile(mod: *Module, file: *File) !void { | ... | @@ -2856,27 +2841,20 @@ pub fn astGenFile(mod: *Module, file: *File) !void { |
| 2856 | } | 2841 | } |
| 2857 | 2842 | ||
| 2858 | if (file.prev_zir) |prev_zir| { | 2843 | if (file.prev_zir) |prev_zir| { |
| 2859 | // Iterate over all Namespace objects contained within this File, looking at the | ||
| 2860 | // previous and new ZIR together and update the references to point | ||
| 2861 | // to the new one. For example, Decl name, Decl zir_decl_index, and Namespace | ||
| 2862 | // decl_table keys need to get updated to point to the new memory, even if the | ||
| 2863 | // underlying source code is unchanged. | ||
| 2864 | // We do not need to hold any locks at this time because all the Decl and Namespace | ||
| 2865 | // objects being touched are specific to this File, and the only other concurrent | ||
| 2866 | // tasks are touching other File objects. | ||
| 2867 | try updateZirRefs(mod, file, prev_zir.*); | 2844 | try updateZirRefs(mod, file, prev_zir.*); |
| 2868 | // At this point, `file.outdated_decls` and `file.deleted_decls` are populated, | ||
| 2869 | // and semantic analysis will deal with them properly. | ||
| 2870 | // No need to keep previous ZIR. | 2845 | // No need to keep previous ZIR. |
| 2871 | prev_zir.deinit(gpa); | 2846 | prev_zir.deinit(gpa); |
| 2872 | gpa.destroy(prev_zir); | 2847 | gpa.destroy(prev_zir); |
| 2873 | file.prev_zir = null; | 2848 | file.prev_zir = null; |
| 2874 | } else if (file.root_decl.unwrap()) |root_decl| { | 2849 | } |
| 2875 | // This is an update, but it is the first time the File has succeeded | 2850 | |
| 2876 | // ZIR. We must mark it outdated since we have already tried to | 2851 | if (file.root_decl.unwrap()) |root_decl| { |
| 2877 | // semantically analyze it. | 2852 | // The root of this file must be re-analyzed, since the file has changed. |
| 2878 | try file.outdated_decls.resize(gpa, 1); | 2853 | comp.mutex.lock(); |
| 2879 | file.outdated_decls.items[0] = root_decl; | 2854 | defer comp.mutex.unlock(); |
| 2855 | |||
| 2856 | log.debug("outdated root Decl: {}", .{root_decl}); | ||
| 2857 | try mod.outdated_file_root.put(gpa, root_decl, {}); | ||
| 2880 | } | 2858 | } |
| 2881 | } | 2859 | } |
| 2882 | 2860 | ||
| ... | @@ -2950,25 +2928,347 @@ fn loadZirCacheBody(gpa: Allocator, header: Zir.Header, cache_file: std.fs.File) | ... | @@ -2950,25 +2928,347 @@ fn loadZirCacheBody(gpa: Allocator, header: Zir.Header, cache_file: std.fs.File) |
| 2950 | return zir; | 2928 | return zir; |
| 2951 | } | 2929 | } |
| 2952 | 2930 | ||
| 2931 | /// This is called from the AstGen thread pool, so must acquire | ||
| 2932 | /// the Compilation mutex when acting on shared state. | ||
| 2953 | fn updateZirRefs(zcu: *Module, file: *File, old_zir: Zir) !void { | 2933 | fn updateZirRefs(zcu: *Module, file: *File, old_zir: Zir) !void { |
| 2954 | const gpa = zcu.gpa; | 2934 | const gpa = zcu.gpa; |
| 2935 | const new_zir = file.zir; | ||
| 2955 | 2936 | ||
| 2956 | var inst_map: std.AutoHashMapUnmanaged(Zir.Inst.Index, Zir.Inst.Index) = .{}; | 2937 | var inst_map: std.AutoHashMapUnmanaged(Zir.Inst.Index, Zir.Inst.Index) = .{}; |
| 2957 | defer inst_map.deinit(gpa); | 2938 | defer inst_map.deinit(gpa); |
| 2958 | 2939 | ||
| 2959 | try mapOldZirToNew(gpa, old_zir, file.zir, &inst_map); | 2940 | try mapOldZirToNew(gpa, old_zir, new_zir, &inst_map); |
| 2941 | |||
| 2942 | const old_tag = old_zir.instructions.items(.tag); | ||
| 2943 | const old_data = old_zir.instructions.items(.data); | ||
| 2960 | 2944 | ||
| 2961 | // TODO: this should be done after all AstGen workers complete, to avoid | 2945 | // TODO: this should be done after all AstGen workers complete, to avoid |
| 2962 | // iterating over this full set for every updated file. | 2946 | // iterating over this full set for every updated file. |
| 2963 | for (zcu.intern_pool.tracked_insts.keys()) |*ti| { | 2947 | for (zcu.intern_pool.tracked_insts.keys(), 0..) |*ti, idx_raw| { |
| 2948 | const ti_idx: InternPool.TrackedInst.Index = @enumFromInt(idx_raw); | ||
| 2964 | if (!std.mem.eql(u8, &ti.path_digest, &file.path_digest)) continue; | 2949 | if (!std.mem.eql(u8, &ti.path_digest, &file.path_digest)) continue; |
| 2950 | const old_inst = ti.inst; | ||
| 2965 | ti.inst = inst_map.get(ti.inst) orelse { | 2951 | ti.inst = inst_map.get(ti.inst) orelse { |
| 2966 | // TODO: invalidate this `TrackedInst` via the dependency mechanism | 2952 | // Tracking failed for this instruction. Invalidate associated `src_hash` deps. |
| 2953 | zcu.comp.mutex.lock(); | ||
| 2954 | defer zcu.comp.mutex.unlock(); | ||
| 2955 | log.debug("tracking failed for %{d}", .{old_inst}); | ||
| 2956 | try zcu.markDependeeOutdated(.{ .src_hash = ti_idx }); | ||
| 2967 | continue; | 2957 | continue; |
| 2968 | }; | 2958 | }; |
| 2959 | |||
| 2960 | if (old_zir.getAssociatedSrcHash(old_inst)) |old_hash| hash_changed: { | ||
| 2961 | if (new_zir.getAssociatedSrcHash(ti.inst)) |new_hash| { | ||
| 2962 | if (std.zig.srcHashEql(old_hash, new_hash)) { | ||
| 2963 | break :hash_changed; | ||
| 2964 | } | ||
| 2965 | log.debug("hash for (%{d} -> %{d}) changed: {} -> {}", .{ | ||
| 2966 | old_inst, | ||
| 2967 | ti.inst, | ||
| 2968 | std.fmt.fmtSliceHexLower(&old_hash), | ||
| 2969 | std.fmt.fmtSliceHexLower(&new_hash), | ||
| 2970 | }); | ||
| 2971 | } | ||
| 2972 | // The source hash associated with this instruction changed - invalidate relevant dependencies. | ||
| 2973 | zcu.comp.mutex.lock(); | ||
| 2974 | defer zcu.comp.mutex.unlock(); | ||
| 2975 | try zcu.markDependeeOutdated(.{ .src_hash = ti_idx }); | ||
| 2976 | } | ||
| 2977 | |||
| 2978 | // If this is a `struct_decl` etc, we must invalidate any outdated namespace dependencies. | ||
| 2979 | const has_namespace = switch (old_tag[@intFromEnum(old_inst)]) { | ||
| 2980 | .extended => switch (old_data[@intFromEnum(old_inst)].extended.opcode) { | ||
| 2981 | .struct_decl, .union_decl, .opaque_decl, .enum_decl => true, | ||
| 2982 | else => false, | ||
| 2983 | }, | ||
| 2984 | else => false, | ||
| 2985 | }; | ||
| 2986 | if (!has_namespace) continue; | ||
| 2987 | |||
| 2988 | var old_names: std.AutoArrayHashMapUnmanaged(InternPool.NullTerminatedString, void) = .{}; | ||
| 2989 | defer old_names.deinit(zcu.gpa); | ||
| 2990 | { | ||
| 2991 | var it = old_zir.declIterator(old_inst); | ||
| 2992 | while (it.next()) |decl_inst| { | ||
| 2993 | const decl_name = old_zir.getDeclaration(decl_inst)[0].name; | ||
| 2994 | switch (decl_name) { | ||
| 2995 | .@"comptime", .@"usingnamespace", .unnamed_test, .decltest => continue, | ||
| 2996 | _ => if (decl_name.isNamedTest(old_zir)) continue, | ||
| 2997 | } | ||
| 2998 | const name_zir = decl_name.toString(old_zir).?; | ||
| 2999 | const name_ip = try zcu.intern_pool.getOrPutString( | ||
| 3000 | zcu.gpa, | ||
| 3001 | old_zir.nullTerminatedString(name_zir), | ||
| 3002 | ); | ||
| 3003 | try old_names.put(zcu.gpa, name_ip, {}); | ||
| 3004 | } | ||
| 3005 | } | ||
| 3006 | var any_change = false; | ||
| 3007 | { | ||
| 3008 | var it = new_zir.declIterator(ti.inst); | ||
| 3009 | while (it.next()) |decl_inst| { | ||
| 3010 | const decl_name = old_zir.getDeclaration(decl_inst)[0].name; | ||
| 3011 | switch (decl_name) { | ||
| 3012 | .@"comptime", .@"usingnamespace", .unnamed_test, .decltest => continue, | ||
| 3013 | _ => if (decl_name.isNamedTest(old_zir)) continue, | ||
| 3014 | } | ||
| 3015 | const name_zir = decl_name.toString(old_zir).?; | ||
| 3016 | const name_ip = try zcu.intern_pool.getOrPutString( | ||
| 3017 | zcu.gpa, | ||
| 3018 | old_zir.nullTerminatedString(name_zir), | ||
| 3019 | ); | ||
| 3020 | if (!old_names.swapRemove(name_ip)) continue; | ||
| 3021 | // Name added | ||
| 3022 | any_change = true; | ||
| 3023 | zcu.comp.mutex.lock(); | ||
| 3024 | defer zcu.comp.mutex.unlock(); | ||
| 3025 | try zcu.markDependeeOutdated(.{ .namespace_name = .{ | ||
| 3026 | .namespace = ti_idx, | ||
| 3027 | .name = name_ip, | ||
| 3028 | } }); | ||
| 3029 | } | ||
| 3030 | } | ||
| 3031 | // The only elements remaining in `old_names` now are any names which were removed. | ||
| 3032 | for (old_names.keys()) |name_ip| { | ||
| 3033 | any_change = true; | ||
| 3034 | zcu.comp.mutex.lock(); | ||
| 3035 | defer zcu.comp.mutex.unlock(); | ||
| 3036 | try zcu.markDependeeOutdated(.{ .namespace_name = .{ | ||
| 3037 | .namespace = ti_idx, | ||
| 3038 | .name = name_ip, | ||
| 3039 | } }); | ||
| 3040 | } | ||
| 3041 | |||
| 3042 | if (any_change) { | ||
| 3043 | zcu.comp.mutex.lock(); | ||
| 3044 | defer zcu.comp.mutex.unlock(); | ||
| 3045 | try zcu.markDependeeOutdated(.{ .namespace = ti_idx }); | ||
| 3046 | } | ||
| 2969 | } | 3047 | } |
| 2970 | } | 3048 | } |
| 2971 | 3049 | ||
| 3050 | pub fn markDependeeOutdated(zcu: *Zcu, dependee: InternPool.Dependee) !void { | ||
| 3051 | log.debug("outdated dependee: {}", .{dependee}); | ||
| 3052 | var it = zcu.intern_pool.dependencyIterator(dependee); | ||
| 3053 | while (it.next()) |depender| { | ||
| 3054 | if (zcu.outdated.contains(depender)) { | ||
| 3055 | // We do not need to increment the PO dep count, as if the outdated | ||
| 3056 | // dependee is a Decl, we had already marked this as PO. | ||
| 3057 | continue; | ||
| 3058 | } | ||
| 3059 | const opt_po_entry = zcu.potentially_outdated.fetchSwapRemove(depender); | ||
| 3060 | try zcu.outdated.putNoClobber( | ||
| 3061 | zcu.gpa, | ||
| 3062 | depender, | ||
| 3063 | // We do not need to increment this count for the same reason as above. | ||
| 3064 | if (opt_po_entry) |e| e.value else 0, | ||
| 3065 | ); | ||
| 3066 | log.debug("outdated: {}", .{depender}); | ||
| 3067 | if (opt_po_entry != null) { | ||
| 3068 | // This is a new entry with no PO dependencies. | ||
| 3069 | try zcu.outdated_ready.put(zcu.gpa, depender, {}); | ||
| 3070 | } | ||
| 3071 | // If this is a Decl and was not previously PO, we must recursively | ||
| 3072 | // mark dependencies on its tyval as PO. | ||
| 3073 | if (opt_po_entry == null) switch (depender.unwrap()) { | ||
| 3074 | .decl => |decl_index| try zcu.markDeclDependenciesPotentiallyOutdated(decl_index), | ||
| 3075 | .func => {}, | ||
| 3076 | }; | ||
| 3077 | } | ||
| 3078 | } | ||
| 3079 | |||
| 3080 | fn markPoDependeeUpToDate(zcu: *Zcu, dependee: InternPool.Dependee) !void { | ||
| 3081 | var it = zcu.intern_pool.dependencyIterator(dependee); | ||
| 3082 | while (it.next()) |depender| { | ||
| 3083 | if (zcu.outdated.getPtr(depender)) |po_dep_count| { | ||
| 3084 | // This depender is already outdated, but it now has one | ||
| 3085 | // less PO dependency! | ||
| 3086 | po_dep_count.* -= 1; | ||
| 3087 | if (po_dep_count.* == 0) { | ||
| 3088 | try zcu.outdated_ready.put(zcu.gpa, depender, {}); | ||
| 3089 | } | ||
| 3090 | continue; | ||
| 3091 | } | ||
| 3092 | // This depender is definitely at least PO, because this Decl was just analyzed | ||
| 3093 | // due to being outdated. | ||
| 3094 | const ptr = zcu.potentially_outdated.getPtr(depender).?; | ||
| 3095 | if (ptr.* > 1) { | ||
| 3096 | ptr.* -= 1; | ||
| 3097 | continue; | ||
| 3098 | } | ||
| 3099 | |||
| 3100 | // This dependency is no longer PO, i.e. is known to be up-to-date. | ||
| 3101 | assert(zcu.potentially_outdated.swapRemove(depender)); | ||
| 3102 | // If this is a Decl, we must recursively mark dependencies on its tyval | ||
| 3103 | // as no longer PO. | ||
| 3104 | switch (depender.unwrap()) { | ||
| 3105 | .decl => |decl_index| try zcu.markPoDependeeUpToDate(.{ .decl_val = decl_index }), | ||
| 3106 | .func => {}, | ||
| 3107 | } | ||
| 3108 | } | ||
| 3109 | } | ||
| 3110 | |||
| 3111 | /// Given a Decl which is newly outdated or PO, mark all dependers which depend | ||
| 3112 | /// on its tyval as PO. | ||
| 3113 | fn markDeclDependenciesPotentiallyOutdated(zcu: *Zcu, decl_index: Decl.Index) !void { | ||
| 3114 | var it = zcu.intern_pool.dependencyIterator(.{ .decl_val = decl_index }); | ||
| 3115 | while (it.next()) |po| { | ||
| 3116 | if (zcu.outdated.getPtr(po)) |po_dep_count| { | ||
| 3117 | // This dependency is already outdated, but it now has one more PO | ||
| 3118 | // dependency. | ||
| 3119 | if (po_dep_count.* == 0) { | ||
| 3120 | _ = zcu.outdated_ready.swapRemove(po); | ||
| 3121 | } | ||
| 3122 | po_dep_count.* += 1; | ||
| 3123 | continue; | ||
| 3124 | } | ||
| 3125 | if (zcu.potentially_outdated.getPtr(po)) |n| { | ||
| 3126 | // There is now one more PO dependency. | ||
| 3127 | n.* += 1; | ||
| 3128 | continue; | ||
| 3129 | } | ||
| 3130 | try zcu.potentially_outdated.putNoClobber(zcu.gpa, po, 1); | ||
| 3131 | // If this ia a Decl, we must recursively mark dependencies | ||
| 3132 | // on its tyval as PO. | ||
| 3133 | switch (po.unwrap()) { | ||
| 3134 | .decl => |po_decl| try zcu.markDeclDependenciesPotentiallyOutdated(po_decl), | ||
| 3135 | .func => {}, | ||
| 3136 | } | ||
| 3137 | } | ||
| 3138 | // TODO: repeat the above for `decl_ty` dependencies when they are introduced | ||
| 3139 | } | ||
| 3140 | |||
| 3141 | pub fn findOutdatedToAnalyze(zcu: *Zcu) Allocator.Error!?InternPool.Depender { | ||
| 3142 | if (!zcu.comp.debug_incremental) return null; | ||
| 3143 | |||
| 3144 | if (zcu.outdated.count() == 0 and zcu.potentially_outdated.count() == 0) { | ||
| 3145 | log.debug("findOutdatedToAnalyze: no outdated depender", .{}); | ||
| 3146 | return null; | ||
| 3147 | } | ||
| 3148 | |||
| 3149 | // Our goal is to find an outdated Depender which itself has no outdated or | ||
| 3150 | // PO dependencies. Most of the time, such a Depender will exist - we track | ||
| 3151 | // them in the `outdated_ready` set for efficiency. However, this is not | ||
| 3152 | // necessarily the case, since the Decl dependency graph may contain loops | ||
| 3153 | // via mutually recursive definitions: | ||
| 3154 | // pub const A = struct { b: *B }; | ||
| 3155 | // pub const B = struct { b: *A }; | ||
| 3156 | // In this case, we must defer to more complex logic below. | ||
| 3157 | |||
| 3158 | if (zcu.outdated_ready.count() > 0) { | ||
| 3159 | log.debug("findOutdatedToAnalyze: trivial '{s} {d}'", .{ | ||
| 3160 | @tagName(zcu.outdated_ready.keys()[0].unwrap()), | ||
| 3161 | switch (zcu.outdated_ready.keys()[0].unwrap()) { | ||
| 3162 | inline else => |x| @intFromEnum(x), | ||
| 3163 | }, | ||
| 3164 | }); | ||
| 3165 | return zcu.outdated_ready.keys()[0]; | ||
| 3166 | } | ||
| 3167 | |||
| 3168 | // Next, we will see if there is any outdated file root which was not in | ||
| 3169 | // `outdated`. This set will be small (number of files changed in this | ||
| 3170 | // update), so it's alright for us to just iterate here. | ||
| 3171 | for (zcu.outdated_file_root.keys()) |file_decl| { | ||
| 3172 | const decl_depender = InternPool.Depender.wrap(.{ .decl = file_decl }); | ||
| 3173 | if (zcu.outdated.contains(decl_depender)) { | ||
| 3174 | // Since we didn't hit this in the first loop, this Decl must have | ||
| 3175 | // pending dependencies, so is ineligible. | ||
| 3176 | continue; | ||
| 3177 | } | ||
| 3178 | if (zcu.potentially_outdated.contains(decl_depender)) { | ||
| 3179 | // This Decl's struct may or may not need to be recreated depending | ||
| 3180 | // on whether it is outdated. If we analyzed it now, we would have | ||
| 3181 | // to assume it was outdated and recreate it! | ||
| 3182 | continue; | ||
| 3183 | } | ||
| 3184 | log.debug("findOutdatedToAnalyze: outdated file root decl '{d}'", .{file_decl}); | ||
| 3185 | return decl_depender; | ||
| 3186 | } | ||
| 3187 | |||
| 3188 | // There is no single Depender which is ready for re-analysis. Instead, we | ||
| 3189 | // must assume that some Decl with PO dependencies is outdated - e.g. in the | ||
| 3190 | // above example we arbitrarily pick one of A or B. We should select a Decl, | ||
| 3191 | // since a Decl is definitely responsible for the loop in the dependency | ||
| 3192 | // graph (since you can't depend on a runtime function analysis!). | ||
| 3193 | |||
| 3194 | // The choice of this Decl could have a big impact on how much total | ||
| 3195 | // analysis we perform, since if analysis concludes its tyval is unchanged, | ||
| 3196 | // then other PO Dependers may be resolved as up-to-date. To hopefully avoid | ||
| 3197 | // doing too much work, let's find a Decl which the most things depend on - | ||
| 3198 | // the idea is that this will resolve a lot of loops (but this is only a | ||
| 3199 | // heuristic). | ||
| 3200 | |||
| 3201 | log.debug("findOutdatedToAnalyze: no trivial ready, using heuristic; {d} outdated, {d} PO", .{ | ||
| 3202 | zcu.outdated.count(), | ||
| 3203 | zcu.potentially_outdated.count(), | ||
| 3204 | }); | ||
| 3205 | |||
| 3206 | var chosen_decl_idx: ?Decl.Index = null; | ||
| 3207 | var chosen_decl_dependers: u32 = undefined; | ||
| 3208 | |||
| 3209 | for (zcu.outdated.keys()) |depender| { | ||
| 3210 | const decl_index = switch (depender.unwrap()) { | ||
| 3211 | .decl => |d| d, | ||
| 3212 | .func => continue, | ||
| 3213 | }; | ||
| 3214 | |||
| 3215 | var n: u32 = 0; | ||
| 3216 | var it = zcu.intern_pool.dependencyIterator(.{ .decl_val = decl_index }); | ||
| 3217 | while (it.next()) |_| n += 1; | ||
| 3218 | |||
| 3219 | if (chosen_decl_idx == null or n > chosen_decl_dependers) { | ||
| 3220 | chosen_decl_idx = decl_index; | ||
| 3221 | chosen_decl_dependers = n; | ||
| 3222 | } | ||
| 3223 | } | ||
| 3224 | |||
| 3225 | for (zcu.potentially_outdated.keys()) |depender| { | ||
| 3226 | const decl_index = switch (depender.unwrap()) { | ||
| 3227 | .decl => |d| d, | ||
| 3228 | .func => continue, | ||
| 3229 | }; | ||
| 3230 | |||
| 3231 | var n: u32 = 0; | ||
| 3232 | var it = zcu.intern_pool.dependencyIterator(.{ .decl_val = decl_index }); | ||
| 3233 | while (it.next()) |_| n += 1; | ||
| 3234 | |||
| 3235 | if (chosen_decl_idx == null or n > chosen_decl_dependers) { | ||
| 3236 | chosen_decl_idx = decl_index; | ||
| 3237 | chosen_decl_dependers = n; | ||
| 3238 | } | ||
| 3239 | } | ||
| 3240 | |||
| 3241 | log.debug("findOutdatedToAnalyze: heuristic returned Decl {d} ({d} dependers)", .{ | ||
| 3242 | chosen_decl_idx.?, | ||
| 3243 | chosen_decl_dependers, | ||
| 3244 | }); | ||
| 3245 | |||
| 3246 | return InternPool.Depender.wrap(.{ .decl = chosen_decl_idx.? }); | ||
| 3247 | } | ||
| 3248 | |||
| 3249 | /// During an incremental update, before semantic analysis, call this to flush all values from | ||
| 3250 | /// `retryable_failures` and mark them as outdated so they get re-analyzed. | ||
| 3251 | pub fn flushRetryableFailures(zcu: *Zcu) !void { | ||
| 3252 | const gpa = zcu.gpa; | ||
| 3253 | for (zcu.retryable_failures.items) |depender| { | ||
| 3254 | if (zcu.outdated.contains(depender)) continue; | ||
| 3255 | if (zcu.potentially_outdated.fetchSwapRemove(depender)) |kv| { | ||
| 3256 | // This Depender was already PO, but we now consider it outdated. | ||
| 3257 | // Any transitive dependencies are already marked PO. | ||
| 3258 | try zcu.outdated.put(gpa, depender, kv.value); | ||
| 3259 | continue; | ||
| 3260 | } | ||
| 3261 | // This Depender was not marked PO, but is now outdated. Mark it as | ||
| 3262 | // such, then recursively mark transitive dependencies as PO. | ||
| 3263 | try zcu.outdated.put(gpa, depender, 0); | ||
| 3264 | switch (depender.unwrap()) { | ||
| 3265 | .decl => |decl| try zcu.markDeclDependenciesPotentiallyOutdated(decl), | ||
| 3266 | .func => {}, | ||
| 3267 | } | ||
| 3268 | } | ||
| 3269 | zcu.retryable_failures.clearRetainingCapacity(); | ||
| 3270 | } | ||
| 3271 | |||
| 2972 | pub fn mapOldZirToNew( | 3272 | pub fn mapOldZirToNew( |
| 2973 | gpa: Allocator, | 3273 | gpa: Allocator, |
| 2974 | old_zir: Zir, | 3274 | old_zir: Zir, |
| ... | @@ -3096,7 +3396,7 @@ pub fn mapOldZirToNew( | ... | @@ -3096,7 +3396,7 @@ pub fn mapOldZirToNew( |
| 3096 | } | 3396 | } |
| 3097 | } | 3397 | } |
| 3098 | 3398 | ||
| 3099 | /// This ensures that the Decl will have a Type and Value populated. | 3399 | /// This ensures that the Decl will have an up-to-date Type and Value populated. |
| 3100 | /// However the resolution status of the Type may not be fully resolved. | 3400 | /// However the resolution status of the Type may not be fully resolved. |
| 3101 | /// For example an inferred error set is not resolved until after `analyzeFnBody`. | 3401 | /// For example an inferred error set is not resolved until after `analyzeFnBody`. |
| 3102 | /// is called. | 3402 | /// is called. |
| ... | @@ -3106,40 +3406,57 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl_index: Decl.Index) SemaError!void { | ... | @@ -3106,40 +3406,57 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl_index: Decl.Index) SemaError!void { |
| 3106 | 3406 | ||
| 3107 | const decl = mod.declPtr(decl_index); | 3407 | const decl = mod.declPtr(decl_index); |
| 3108 | 3408 | ||
| 3109 | const subsequent_analysis = switch (decl.analysis) { | 3409 | // Determine whether or not this Decl is outdated, i.e. requires re-analysis |
| 3410 | // even if `complete`. If a Decl is PO, we pessismistically assume that it | ||
| 3411 | // *does* require re-analysis, to ensure that the Decl is definitely | ||
| 3412 | // up-to-date when this function returns. | ||
| 3413 | |||
| 3414 | // If analysis occurs in a poor order, this could result in over-analysis. | ||
| 3415 | // We do our best to avoid this by the other dependency logic in this file | ||
| 3416 | // which tries to limit re-analysis to Decls whose previously listed | ||
| 3417 | // dependencies are all up-to-date. | ||
| 3418 | |||
| 3419 | const decl_as_depender = InternPool.Depender.wrap(.{ .decl = decl_index }); | ||
| 3420 | const was_outdated = mod.outdated.swapRemove(decl_as_depender) or | ||
| 3421 | mod.potentially_outdated.swapRemove(decl_as_depender); | ||
| 3422 | |||
| 3423 | if (was_outdated) { | ||
| 3424 | _ = mod.outdated_ready.swapRemove(decl_as_depender); | ||
| 3425 | } | ||
| 3426 | |||
| 3427 | switch (decl.analysis) { | ||
| 3110 | .in_progress => unreachable, | 3428 | .in_progress => unreachable, |
| 3111 | 3429 | ||
| 3112 | .file_failure, | 3430 | .file_failure => return error.AnalysisFail, |
| 3431 | |||
| 3113 | .sema_failure, | 3432 | .sema_failure, |
| 3114 | .sema_failure_retryable, | ||
| 3115 | .liveness_failure, | ||
| 3116 | .codegen_failure, | ||
| 3117 | .dependency_failure, | 3433 | .dependency_failure, |
| 3118 | .codegen_failure_retryable, | 3434 | .codegen_failure, |
| 3119 | => return error.AnalysisFail, | 3435 | => if (!was_outdated) return error.AnalysisFail, |
| 3120 | |||
| 3121 | .complete => return, | ||
| 3122 | 3436 | ||
| 3123 | .outdated => blk: { | 3437 | .complete => if (!was_outdated) return, |
| 3124 | if (build_options.only_c) unreachable; | ||
| 3125 | // The exports this Decl performs will be re-discovered, so we remove them here | ||
| 3126 | // prior to re-analysis. | ||
| 3127 | try mod.deleteDeclExports(decl_index); | ||
| 3128 | 3438 | ||
| 3129 | break :blk true; | 3439 | .unreferenced => {}, |
| 3130 | }, | 3440 | } |
| 3131 | 3441 | ||
| 3132 | .unreferenced => false, | 3442 | if (was_outdated) { |
| 3133 | }; | 3443 | // The exports this Decl performs will be re-discovered, so we remove them here |
| 3444 | // prior to re-analysis. | ||
| 3445 | if (build_options.only_c) unreachable; | ||
| 3446 | try mod.deleteDeclExports(decl_index); | ||
| 3447 | } | ||
| 3134 | 3448 | ||
| 3135 | var decl_prog_node = mod.sema_prog_node.start("", 0); | 3449 | var decl_prog_node = mod.sema_prog_node.start("", 0); |
| 3136 | decl_prog_node.activate(); | 3450 | decl_prog_node.activate(); |
| 3137 | defer decl_prog_node.end(); | 3451 | defer decl_prog_node.end(); |
| 3138 | 3452 | ||
| 3139 | const type_changed = blk: { | 3453 | const sema_result: SemaDeclResult = blk: { |
| 3140 | if (decl.zir_decl_index == .none and !mod.declIsRoot(decl_index)) { | 3454 | if (decl.zir_decl_index == .none and !mod.declIsRoot(decl_index)) { |
| 3141 | // Anonymous decl. We don't semantically analyze these. | 3455 | // Anonymous decl. We don't semantically analyze these. |
| 3142 | break :blk false; // tv unchanged | 3456 | break :blk .{ |
| 3457 | .invalidate_decl_val = false, | ||
| 3458 | .invalidate_decl_ref = false, | ||
| 3459 | }; | ||
| 3143 | } | 3460 | } |
| 3144 | 3461 | ||
| 3145 | break :blk mod.semaDecl(decl_index) catch |err| switch (err) { | 3462 | break :blk mod.semaDecl(decl_index) catch |err| switch (err) { |
| ... | @@ -3155,8 +3472,9 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl_index: Decl.Index) SemaError!void { | ... | @@ -3155,8 +3472,9 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl_index: Decl.Index) SemaError!void { |
| 3155 | error.NeededSourceLocation => unreachable, | 3472 | error.NeededSourceLocation => unreachable, |
| 3156 | error.GenericPoison => unreachable, | 3473 | error.GenericPoison => unreachable, |
| 3157 | else => |e| { | 3474 | else => |e| { |
| 3158 | decl.analysis = .sema_failure_retryable; | 3475 | decl.analysis = .sema_failure; |
| 3159 | try mod.failed_decls.ensureUnusedCapacity(mod.gpa, 1); | 3476 | try mod.failed_decls.ensureUnusedCapacity(mod.gpa, 1); |
| 3477 | try mod.retryable_failures.append(mod.gpa, InternPool.Depender.wrap(.{ .decl = decl_index })); | ||
| 3160 | mod.failed_decls.putAssumeCapacityNoClobber(decl_index, try ErrorMsg.create( | 3478 | mod.failed_decls.putAssumeCapacityNoClobber(decl_index, try ErrorMsg.create( |
| 3161 | mod.gpa, | 3479 | mod.gpa, |
| 3162 | decl.srcLoc(mod), | 3480 | decl.srcLoc(mod), |
| ... | @@ -3168,9 +3486,18 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl_index: Decl.Index) SemaError!void { | ... | @@ -3168,9 +3486,18 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl_index: Decl.Index) SemaError!void { |
| 3168 | }; | 3486 | }; |
| 3169 | }; | 3487 | }; |
| 3170 | 3488 | ||
| 3171 | if (subsequent_analysis) { | 3489 | // TODO: we do not yet have separate dependencies for decl values vs types. |
| 3172 | _ = type_changed; | 3490 | if (was_outdated) { |
| 3173 | @panic("TODO re-implement incremental compilation"); | 3491 | if (sema_result.invalidate_decl_val or sema_result.invalidate_decl_ref) { |
| 3492 | // This dependency was marked as PO, meaning dependees were waiting | ||
| 3493 | // on its analysis result, and it has turned out to be outdated. | ||
| 3494 | // Update dependees accordingly. | ||
| 3495 | try mod.markDependeeOutdated(.{ .decl_val = decl_index }); | ||
| 3496 | } else { | ||
| 3497 | // This dependency was previously PO, but turned out to be up-to-date. | ||
| 3498 | // We do not need to queue successive analysis. | ||
| 3499 | try mod.markPoDependeeUpToDate(.{ .decl_val = decl_index }); | ||
| 3500 | } | ||
| 3174 | } | 3501 | } |
| 3175 | } | 3502 | } |
| 3176 | 3503 | ||
| ... | @@ -3186,119 +3513,129 @@ pub fn ensureFuncBodyAnalyzed(zcu: *Zcu, func_index: InternPool.Index) SemaError | ... | @@ -3186,119 +3513,129 @@ pub fn ensureFuncBodyAnalyzed(zcu: *Zcu, func_index: InternPool.Index) SemaError |
| 3186 | switch (decl.analysis) { | 3513 | switch (decl.analysis) { |
| 3187 | .unreferenced => unreachable, | 3514 | .unreferenced => unreachable, |
| 3188 | .in_progress => unreachable, | 3515 | .in_progress => unreachable, |
| 3189 | .outdated => unreachable, | 3516 | |
| 3517 | .codegen_failure => unreachable, // functions do not perform constant value generation | ||
| 3190 | 3518 | ||
| 3191 | .file_failure, | 3519 | .file_failure, |
| 3192 | .sema_failure, | 3520 | .sema_failure, |
| 3193 | .liveness_failure, | ||
| 3194 | .codegen_failure, | ||
| 3195 | .dependency_failure, | 3521 | .dependency_failure, |
| 3196 | .sema_failure_retryable, | ||
| 3197 | => return error.AnalysisFail, | 3522 | => return error.AnalysisFail, |
| 3198 | 3523 | ||
| 3199 | .complete, .codegen_failure_retryable => { | 3524 | .complete => {}, |
| 3200 | switch (func.analysis(ip).state) { | 3525 | } |
| 3201 | .sema_failure, .dependency_failure => return error.AnalysisFail, | ||
| 3202 | .none, .queued => {}, | ||
| 3203 | .in_progress => unreachable, | ||
| 3204 | .inline_only => unreachable, // don't queue work for this | ||
| 3205 | .success => return, | ||
| 3206 | } | ||
| 3207 | 3526 | ||
| 3208 | const gpa = zcu.gpa; | 3527 | const func_as_depender = InternPool.Depender.wrap(.{ .func = func_index }); |
| 3528 | const was_outdated = zcu.outdated.swapRemove(func_as_depender) or | ||
| 3529 | zcu.potentially_outdated.swapRemove(func_as_depender); | ||
| 3209 | 3530 | ||
| 3210 | var tmp_arena = std.heap.ArenaAllocator.init(gpa); | 3531 | if (was_outdated) { |
| 3211 | defer tmp_arena.deinit(); | 3532 | _ = zcu.outdated_ready.swapRemove(func_as_depender); |
| 3212 | const sema_arena = tmp_arena.allocator(); | 3533 | } |
| 3213 | 3534 | ||
| 3214 | var air = zcu.analyzeFnBody(func_index, sema_arena) catch |err| switch (err) { | 3535 | switch (func.analysis(ip).state) { |
| 3215 | error.AnalysisFail => { | 3536 | .success, |
| 3216 | if (func.analysis(ip).state == .in_progress) { | 3537 | .sema_failure, |
| 3217 | // If this decl caused the compile error, the analysis field would | 3538 | .dependency_failure, |
| 3218 | // be changed to indicate it was this Decl's fault. Because this | 3539 | .codegen_failure, |
| 3219 | // did not happen, we infer here that it was a dependency failure. | 3540 | => if (!was_outdated) return error.AnalysisFail, |
| 3220 | func.analysis(ip).state = .dependency_failure; | 3541 | .none, .queued => {}, |
| 3221 | } | 3542 | .in_progress => unreachable, |
| 3222 | return error.AnalysisFail; | 3543 | .inline_only => unreachable, // don't queue work for this |
| 3223 | }, | 3544 | } |
| 3224 | error.OutOfMemory => return error.OutOfMemory, | ||
| 3225 | }; | ||
| 3226 | defer air.deinit(gpa); | ||
| 3227 | 3545 | ||
| 3228 | const comp = zcu.comp; | 3546 | const gpa = zcu.gpa; |
| 3229 | 3547 | ||
| 3230 | const dump_air = builtin.mode == .Debug and comp.verbose_air; | 3548 | var tmp_arena = std.heap.ArenaAllocator.init(gpa); |
| 3231 | const dump_llvm_ir = builtin.mode == .Debug and (comp.verbose_llvm_ir != null or comp.verbose_llvm_bc != null); | 3549 | defer tmp_arena.deinit(); |
| 3550 | const sema_arena = tmp_arena.allocator(); | ||
| 3232 | 3551 | ||
| 3233 | if (comp.bin_file == null and zcu.llvm_object == null and !dump_air and !dump_llvm_ir) { | 3552 | var air = zcu.analyzeFnBody(func_index, sema_arena) catch |err| switch (err) { |
| 3234 | return; | 3553 | error.AnalysisFail => { |
| 3554 | if (func.analysis(ip).state == .in_progress) { | ||
| 3555 | // If this decl caused the compile error, the analysis field would | ||
| 3556 | // be changed to indicate it was this Decl's fault. Because this | ||
| 3557 | // did not happen, we infer here that it was a dependency failure. | ||
| 3558 | func.analysis(ip).state = .dependency_failure; | ||
| 3235 | } | 3559 | } |
| 3560 | return error.AnalysisFail; | ||
| 3561 | }, | ||
| 3562 | error.OutOfMemory => return error.OutOfMemory, | ||
| 3563 | }; | ||
| 3564 | defer air.deinit(gpa); | ||
| 3236 | 3565 | ||
| 3237 | var liveness = try Liveness.analyze(gpa, air, ip); | 3566 | const comp = zcu.comp; |
| 3238 | defer liveness.deinit(gpa); | ||
| 3239 | 3567 | ||
| 3240 | if (dump_air) { | 3568 | const dump_air = builtin.mode == .Debug and comp.verbose_air; |
| 3241 | const fqn = try decl.getFullyQualifiedName(zcu); | 3569 | const dump_llvm_ir = builtin.mode == .Debug and (comp.verbose_llvm_ir != null or comp.verbose_llvm_bc != null); |
| 3242 | std.debug.print("# Begin Function AIR: {}:\n", .{fqn.fmt(ip)}); | ||
| 3243 | @import("print_air.zig").dump(zcu, air, liveness); | ||
| 3244 | std.debug.print("# End Function AIR: {}\n\n", .{fqn.fmt(ip)}); | ||
| 3245 | } | ||
| 3246 | 3570 | ||
| 3247 | if (std.debug.runtime_safety) { | 3571 | if (comp.bin_file == null and zcu.llvm_object == null and !dump_air and !dump_llvm_ir) { |
| 3248 | var verify = Liveness.Verify{ | 3572 | return; |
| 3249 | .gpa = gpa, | 3573 | } |
| 3250 | .air = air, | ||
| 3251 | .liveness = liveness, | ||
| 3252 | .intern_pool = ip, | ||
| 3253 | }; | ||
| 3254 | defer verify.deinit(); | ||
| 3255 | |||
| 3256 | verify.verify() catch |err| switch (err) { | ||
| 3257 | error.OutOfMemory => return error.OutOfMemory, | ||
| 3258 | else => { | ||
| 3259 | try zcu.failed_decls.ensureUnusedCapacity(gpa, 1); | ||
| 3260 | zcu.failed_decls.putAssumeCapacityNoClobber( | ||
| 3261 | decl_index, | ||
| 3262 | try Module.ErrorMsg.create( | ||
| 3263 | gpa, | ||
| 3264 | decl.srcLoc(zcu), | ||
| 3265 | "invalid liveness: {s}", | ||
| 3266 | .{@errorName(err)}, | ||
| 3267 | ), | ||
| 3268 | ); | ||
| 3269 | decl.analysis = .liveness_failure; | ||
| 3270 | return error.AnalysisFail; | ||
| 3271 | }, | ||
| 3272 | }; | ||
| 3273 | } | ||
| 3274 | 3574 | ||
| 3275 | if (comp.bin_file) |lf| { | 3575 | var liveness = try Liveness.analyze(gpa, air, ip); |
| 3276 | lf.updateFunc(zcu, func_index, air, liveness) catch |err| switch (err) { | 3576 | defer liveness.deinit(gpa); |
| 3277 | error.OutOfMemory => return error.OutOfMemory, | 3577 | |
| 3278 | error.AnalysisFail => { | 3578 | if (dump_air) { |
| 3279 | decl.analysis = .codegen_failure; | 3579 | const fqn = try decl.getFullyQualifiedName(zcu); |
| 3280 | }, | 3580 | std.debug.print("# Begin Function AIR: {}:\n", .{fqn.fmt(ip)}); |
| 3281 | else => { | 3581 | @import("print_air.zig").dump(zcu, air, liveness); |
| 3282 | try zcu.failed_decls.ensureUnusedCapacity(gpa, 1); | 3582 | std.debug.print("# End Function AIR: {}\n\n", .{fqn.fmt(ip)}); |
| 3283 | zcu.failed_decls.putAssumeCapacityNoClobber(decl_index, try Module.ErrorMsg.create( | 3583 | } |
| 3284 | gpa, | 3584 | |
| 3285 | decl.srcLoc(zcu), | 3585 | if (std.debug.runtime_safety) { |
| 3286 | "unable to codegen: {s}", | 3586 | var verify = Liveness.Verify{ |
| 3287 | .{@errorName(err)}, | 3587 | .gpa = gpa, |
| 3288 | )); | 3588 | .air = air, |
| 3289 | decl.analysis = .codegen_failure_retryable; | 3589 | .liveness = liveness, |
| 3290 | }, | 3590 | .intern_pool = ip, |
| 3291 | }; | 3591 | }; |
| 3292 | } else if (zcu.llvm_object) |llvm_object| { | 3592 | defer verify.deinit(); |
| 3293 | if (build_options.only_c) unreachable; | 3593 | |
| 3294 | llvm_object.updateFunc(zcu, func_index, air, liveness) catch |err| switch (err) { | 3594 | verify.verify() catch |err| switch (err) { |
| 3295 | error.OutOfMemory => return error.OutOfMemory, | 3595 | error.OutOfMemory => return error.OutOfMemory, |
| 3296 | error.AnalysisFail => { | 3596 | else => { |
| 3297 | decl.analysis = .codegen_failure; | 3597 | try zcu.failed_decls.ensureUnusedCapacity(gpa, 1); |
| 3298 | }, | 3598 | zcu.failed_decls.putAssumeCapacityNoClobber( |
| 3299 | }; | 3599 | decl_index, |
| 3300 | } | 3600 | try Module.ErrorMsg.create( |
| 3301 | }, | 3601 | gpa, |
| 3602 | decl.srcLoc(zcu), | ||
| 3603 | "invalid liveness: {s}", | ||
| 3604 | .{@errorName(err)}, | ||
| 3605 | ), | ||
| 3606 | ); | ||
| 3607 | func.analysis(ip).state = .codegen_failure; | ||
| 3608 | return; | ||
| 3609 | }, | ||
| 3610 | }; | ||
| 3611 | } | ||
| 3612 | |||
| 3613 | if (comp.bin_file) |lf| { | ||
| 3614 | lf.updateFunc(zcu, func_index, air, liveness) catch |err| switch (err) { | ||
| 3615 | error.OutOfMemory => return error.OutOfMemory, | ||
| 3616 | error.AnalysisFail => { | ||
| 3617 | func.analysis(ip).state = .codegen_failure; | ||
| 3618 | }, | ||
| 3619 | else => { | ||
| 3620 | try zcu.failed_decls.ensureUnusedCapacity(gpa, 1); | ||
| 3621 | zcu.failed_decls.putAssumeCapacityNoClobber(decl_index, try Module.ErrorMsg.create( | ||
| 3622 | gpa, | ||
| 3623 | decl.srcLoc(zcu), | ||
| 3624 | "unable to codegen: {s}", | ||
| 3625 | .{@errorName(err)}, | ||
| 3626 | )); | ||
| 3627 | func.analysis(ip).state = .codegen_failure; | ||
| 3628 | try zcu.retryable_failures.append(zcu.gpa, InternPool.Depender.wrap(.{ .func = func_index })); | ||
| 3629 | }, | ||
| 3630 | }; | ||
| 3631 | } else if (zcu.llvm_object) |llvm_object| { | ||
| 3632 | if (build_options.only_c) unreachable; | ||
| 3633 | llvm_object.updateFunc(zcu, func_index, air, liveness) catch |err| switch (err) { | ||
| 3634 | error.OutOfMemory => return error.OutOfMemory, | ||
| 3635 | error.AnalysisFail => { | ||
| 3636 | func.analysis(ip).state = .codegen_failure; | ||
| 3637 | }, | ||
| 3638 | }; | ||
| 3302 | } | 3639 | } |
| 3303 | } | 3640 | } |
| 3304 | 3641 | ||
| ... | @@ -3318,18 +3655,14 @@ pub fn ensureFuncBodyAnalysisQueued(mod: *Module, func_index: InternPool.Index) | ... | @@ -3318,18 +3655,14 @@ pub fn ensureFuncBodyAnalysisQueued(mod: *Module, func_index: InternPool.Index) |
| 3318 | switch (decl.analysis) { | 3655 | switch (decl.analysis) { |
| 3319 | .unreferenced => unreachable, | 3656 | .unreferenced => unreachable, |
| 3320 | .in_progress => unreachable, | 3657 | .in_progress => unreachable, |
| 3321 | .outdated => unreachable, | ||
| 3322 | 3658 | ||
| 3323 | .file_failure, | 3659 | .file_failure, |
| 3324 | .sema_failure, | 3660 | .sema_failure, |
| 3325 | .liveness_failure, | ||
| 3326 | .codegen_failure, | 3661 | .codegen_failure, |
| 3327 | .dependency_failure, | 3662 | .dependency_failure, |
| 3328 | .sema_failure_retryable, | 3663 | // Analysis of the function Decl itself failed, but we've already |
| 3329 | .codegen_failure_retryable, | 3664 | // emitted an error for that. The callee doesn't need the function to be |
| 3330 | // The function analysis failed, but we've already emitted an error for | 3665 | // analyzed right now, so its analysis can safely continue. |
| 3331 | // that. The callee doesn't need the function to be analyzed right now, | ||
| 3332 | // so its analysis can safely continue. | ||
| 3333 | => return, | 3666 | => return, |
| 3334 | 3667 | ||
| 3335 | .complete => {}, | 3668 | .complete => {}, |
| ... | @@ -3337,14 +3670,21 @@ pub fn ensureFuncBodyAnalysisQueued(mod: *Module, func_index: InternPool.Index) | ... | @@ -3337,14 +3670,21 @@ pub fn ensureFuncBodyAnalysisQueued(mod: *Module, func_index: InternPool.Index) |
| 3337 | 3670 | ||
| 3338 | assert(decl.has_tv); | 3671 | assert(decl.has_tv); |
| 3339 | 3672 | ||
| 3673 | const func_as_depender = InternPool.Depender.wrap(.{ .func = func_index }); | ||
| 3674 | const is_outdated = mod.outdated.contains(func_as_depender) or | ||
| 3675 | mod.potentially_outdated.contains(func_as_depender); | ||
| 3676 | |||
| 3340 | switch (func.analysis(ip).state) { | 3677 | switch (func.analysis(ip).state) { |
| 3341 | .none => {}, | 3678 | .none => {}, |
| 3342 | .queued => return, | 3679 | .queued => return, |
| 3343 | // As above, we don't need to forward errors here. | 3680 | // As above, we don't need to forward errors here. |
| 3344 | .sema_failure, .dependency_failure => return, | 3681 | .sema_failure, |
| 3682 | .dependency_failure, | ||
| 3683 | .codegen_failure, | ||
| 3684 | .success, | ||
| 3685 | => if (!is_outdated) return, | ||
| 3345 | .in_progress => return, | 3686 | .in_progress => return, |
| 3346 | .inline_only => unreachable, // don't queue work for this | 3687 | .inline_only => unreachable, // don't queue work for this |
| 3347 | .success => return, | ||
| 3348 | } | 3688 | } |
| 3349 | 3689 | ||
| 3350 | // Decl itself is safely analyzed, and body analysis is not yet queued | 3690 | // Decl itself is safely analyzed, and body analysis is not yet queued |
| ... | @@ -3404,7 +3744,6 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void { | ... | @@ -3404,7 +3744,6 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void { |
| 3404 | new_decl.@"linksection" = .none; | 3744 | new_decl.@"linksection" = .none; |
| 3405 | new_decl.alive = true; // This Decl corresponds to a File and is therefore always alive. | 3745 | new_decl.alive = true; // This Decl corresponds to a File and is therefore always alive. |
| 3406 | new_decl.analysis = .in_progress; | 3746 | new_decl.analysis = .in_progress; |
| 3407 | new_decl.generation = mod.generation; | ||
| 3408 | 3747 | ||
| 3409 | if (file.status != .success_zir) { | 3748 | if (file.status != .success_zir) { |
| 3410 | new_decl.analysis = .file_failure; | 3749 | new_decl.analysis = .file_failure; |
| ... | @@ -3483,12 +3822,19 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void { | ... | @@ -3483,12 +3822,19 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void { |
| 3483 | }, | 3822 | }, |
| 3484 | .incremental => {}, | 3823 | .incremental => {}, |
| 3485 | } | 3824 | } |
| 3825 | |||
| 3826 | // Since this is our first time analyzing this file, there can be no dependencies on | ||
| 3827 | // its root Decl. Thus, we do not need to invalidate any dependencies. | ||
| 3486 | } | 3828 | } |
| 3487 | 3829 | ||
| 3488 | /// Returns `true` if the Decl type changed. | 3830 | const SemaDeclResult = packed struct { |
| 3489 | /// Returns `true` if this is the first time analyzing the Decl. | 3831 | /// Whether the value of a `decl_val` of this Decl changed. |
| 3490 | /// Returns `false` otherwise. | 3832 | invalidate_decl_val: bool, |
| 3491 | fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { | 3833 | /// Whether the type of a `decl_ref` of this Decl changed. |
| 3834 | invalidate_decl_ref: bool, | ||
| 3835 | }; | ||
| 3836 | |||
| 3837 | fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult { | ||
| 3492 | const tracy = trace(@src()); | 3838 | const tracy = trace(@src()); |
| 3493 | defer tracy.end(); | 3839 | defer tracy.end(); |
| 3494 | 3840 | ||
| ... | @@ -3499,6 +3845,15 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { | ... | @@ -3499,6 +3845,15 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { |
| 3499 | return error.AnalysisFail; | 3845 | return error.AnalysisFail; |
| 3500 | } | 3846 | } |
| 3501 | 3847 | ||
| 3848 | if (mod.declIsRoot(decl_index)) { | ||
| 3849 | // This comes from an `analyze_decl` job on an incremental update where | ||
| 3850 | // this file changed. | ||
| 3851 | @panic("TODO: update root Decl of modified file"); | ||
| 3852 | } else if (decl.owns_tv) { | ||
| 3853 | // We are re-analyzing an owner Decl (for a function or a namespace type). | ||
| 3854 | @panic("TODO: update owner Decl"); | ||
| 3855 | } | ||
| 3856 | |||
| 3502 | const gpa = mod.gpa; | 3857 | const gpa = mod.gpa; |
| 3503 | const zir = decl.getFileScope(mod).zir; | 3858 | const zir = decl.getFileScope(mod).zir; |
| 3504 | 3859 | ||
| ... | @@ -3535,6 +3890,8 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { | ... | @@ -3535,6 +3890,8 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { |
| 3535 | break :blk .none; | 3890 | break :blk .none; |
| 3536 | }; | 3891 | }; |
| 3537 | 3892 | ||
| 3893 | mod.intern_pool.removeDependenciesForDepender(gpa, InternPool.Depender.wrap(.{ .decl = decl_index })); | ||
| 3894 | |||
| 3538 | decl.analysis = .in_progress; | 3895 | decl.analysis = .in_progress; |
| 3539 | 3896 | ||
| 3540 | var analysis_arena = std.heap.ArenaAllocator.init(gpa); | 3897 | var analysis_arena = std.heap.ArenaAllocator.init(gpa); |
| ... | @@ -3564,7 +3921,12 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { | ... | @@ -3564,7 +3921,12 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { |
| 3564 | }; | 3921 | }; |
| 3565 | defer sema.deinit(); | 3922 | defer sema.deinit(); |
| 3566 | 3923 | ||
| 3567 | assert(!mod.declIsRoot(decl_index)); | 3924 | // Every Decl (other than file root Decls, which do not have a ZIR index) has a dependency on its own source. |
| 3925 | try sema.declareDependency(.{ .src_hash = try ip.trackZir( | ||
| 3926 | sema.gpa, | ||
| 3927 | decl.getFileScope(mod), | ||
| 3928 | decl.zir_decl_index.unwrap().?, | ||
| 3929 | ) }); | ||
| 3568 | 3930 | ||
| 3569 | var block_scope: Sema.Block = .{ | 3931 | var block_scope: Sema.Block = .{ |
| 3570 | .parent = null, | 3932 | .parent = null, |
| ... | @@ -3620,9 +3982,12 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { | ... | @@ -3620,9 +3982,12 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { |
| 3620 | decl.has_tv = true; | 3982 | decl.has_tv = true; |
| 3621 | decl.owns_tv = false; | 3983 | decl.owns_tv = false; |
| 3622 | decl.analysis = .complete; | 3984 | decl.analysis = .complete; |
| 3623 | decl.generation = mod.generation; | ||
| 3624 | 3985 | ||
| 3625 | return true; | 3986 | // TODO: usingnamespace cannot currently participate in incremental compilation |
| 3987 | return .{ | ||
| 3988 | .invalidate_decl_val = true, | ||
| 3989 | .invalidate_decl_ref = true, | ||
| 3990 | }; | ||
| 3626 | } | 3991 | } |
| 3627 | 3992 | ||
| 3628 | switch (ip.indexToKey(decl_tv.val.toIntern())) { | 3993 | switch (ip.indexToKey(decl_tv.val.toIntern())) { |
| ... | @@ -3647,7 +4012,6 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { | ... | @@ -3647,7 +4012,6 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { |
| 3647 | decl.has_tv = true; | 4012 | decl.has_tv = true; |
| 3648 | decl.owns_tv = owns_tv; | 4013 | decl.owns_tv = owns_tv; |
| 3649 | decl.analysis = .complete; | 4014 | decl.analysis = .complete; |
| 3650 | decl.generation = mod.generation; | ||
| 3651 | 4015 | ||
| 3652 | const is_inline = decl.ty.fnCallingConvention(mod) == .Inline; | 4016 | const is_inline = decl.ty.fnCallingConvention(mod) == .Inline; |
| 3653 | if (decl.is_exported) { | 4017 | if (decl.is_exported) { |
| ... | @@ -3658,15 +4022,16 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { | ... | @@ -3658,15 +4022,16 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { |
| 3658 | // The scope needs to have the decl in it. | 4022 | // The scope needs to have the decl in it. |
| 3659 | try sema.analyzeExport(&block_scope, export_src, .{ .name = decl.name }, decl_index); | 4023 | try sema.analyzeExport(&block_scope, export_src, .{ .name = decl.name }, decl_index); |
| 3660 | } | 4024 | } |
| 3661 | return type_changed or is_inline != prev_is_inline; | 4025 | // TODO: align, linksection, addrspace? |
| 4026 | const changed = type_changed or is_inline != prev_is_inline; | ||
| 4027 | return .{ | ||
| 4028 | .invalidate_decl_val = changed, | ||
| 4029 | .invalidate_decl_ref = changed, | ||
| 4030 | }; | ||
| 3662 | } | 4031 | } |
| 3663 | }, | 4032 | }, |
| 3664 | else => {}, | 4033 | else => {}, |
| 3665 | } | 4034 | } |
| 3666 | var type_changed = true; | ||
| 3667 | if (decl.has_tv) { | ||
| 3668 | type_changed = !decl.ty.eql(decl_tv.ty, mod); | ||
| 3669 | } | ||
| 3670 | 4035 | ||
| 3671 | decl.owns_tv = false; | 4036 | decl.owns_tv = false; |
| 3672 | var queue_linker_work = false; | 4037 | var queue_linker_work = false; |
| ... | @@ -3694,6 +4059,14 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { | ... | @@ -3694,6 +4059,14 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { |
| 3694 | }, | 4059 | }, |
| 3695 | } | 4060 | } |
| 3696 | 4061 | ||
| 4062 | const old_has_tv = decl.has_tv; | ||
| 4063 | // The following values are ignored if `!old_has_tv` | ||
| 4064 | const old_ty = decl.ty; | ||
| 4065 | const old_val = decl.val; | ||
| 4066 | const old_align = decl.alignment; | ||
| 4067 | const old_linksection = decl.@"linksection"; | ||
| 4068 | const old_addrspace = decl.@"addrspace"; | ||
| 4069 | |||
| 3697 | decl.ty = decl_tv.ty; | 4070 | decl.ty = decl_tv.ty; |
| 3698 | decl.val = Value.fromInterned((try decl_tv.val.intern(decl_tv.ty, mod))); | 4071 | decl.val = Value.fromInterned((try decl_tv.val.intern(decl_tv.ty, mod))); |
| 3699 | decl.alignment = blk: { | 4072 | decl.alignment = blk: { |
| ... | @@ -3735,7 +4108,17 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { | ... | @@ -3735,7 +4108,17 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { |
| 3735 | }; | 4108 | }; |
| 3736 | decl.has_tv = true; | 4109 | decl.has_tv = true; |
| 3737 | decl.analysis = .complete; | 4110 | decl.analysis = .complete; |
| 3738 | decl.generation = mod.generation; | 4111 | |
| 4112 | const result: SemaDeclResult = if (old_has_tv) .{ | ||
| 4113 | .invalidate_decl_val = !decl.ty.eql(old_ty, mod) or !decl.val.eql(old_val, decl.ty, mod), | ||
| 4114 | .invalidate_decl_ref = !decl.ty.eql(old_ty, mod) or | ||
| 4115 | decl.alignment != old_align or | ||
| 4116 | decl.@"linksection" != old_linksection or | ||
| 4117 | decl.@"addrspace" != old_addrspace, | ||
| 4118 | } else .{ | ||
| 4119 | .invalidate_decl_val = true, | ||
| 4120 | .invalidate_decl_ref = true, | ||
| 4121 | }; | ||
| 3739 | 4122 | ||
| 3740 | const has_runtime_bits = is_extern or | 4123 | const has_runtime_bits = is_extern or |
| 3741 | (queue_linker_work and try sema.typeHasRuntimeBits(decl.ty)); | 4124 | (queue_linker_work and try sema.typeHasRuntimeBits(decl.ty)); |
| ... | @@ -3748,7 +4131,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { | ... | @@ -3748,7 +4131,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { |
| 3748 | 4131 | ||
| 3749 | try mod.comp.work_queue.writeItem(.{ .codegen_decl = decl_index }); | 4132 | try mod.comp.work_queue.writeItem(.{ .codegen_decl = decl_index }); |
| 3750 | 4133 | ||
| 3751 | if (type_changed and mod.emit_h != null) { | 4134 | if (result.invalidate_decl_ref and mod.emit_h != null) { |
| 3752 | try mod.comp.work_queue.writeItem(.{ .emit_h_decl = decl_index }); | 4135 | try mod.comp.work_queue.writeItem(.{ .emit_h_decl = decl_index }); |
| 3753 | } | 4136 | } |
| 3754 | } | 4137 | } |
| ... | @@ -3759,7 +4142,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { | ... | @@ -3759,7 +4142,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { |
| 3759 | try sema.analyzeExport(&block_scope, export_src, .{ .name = decl.name }, decl_index); | 4142 | try sema.analyzeExport(&block_scope, export_src, .{ .name = decl.name }, decl_index); |
| 3760 | } | 4143 | } |
| 3761 | 4144 | ||
| 3762 | return type_changed; | 4145 | return result; |
| 3763 | } | 4146 | } |
| 3764 | 4147 | ||
| 3765 | pub const ImportFileResult = struct { | 4148 | pub const ImportFileResult = struct { |
| ... | @@ -4362,6 +4745,8 @@ pub fn analyzeFnBody(mod: *Module, func_index: InternPool.Index, arena: Allocato | ... | @@ -4362,6 +4745,8 @@ pub fn analyzeFnBody(mod: *Module, func_index: InternPool.Index, arena: Allocato |
| 4362 | const decl_index = func.owner_decl; | 4745 | const decl_index = func.owner_decl; |
| 4363 | const decl = mod.declPtr(decl_index); | 4746 | const decl = mod.declPtr(decl_index); |
| 4364 | 4747 | ||
| 4748 | mod.intern_pool.removeDependenciesForDepender(gpa, InternPool.Depender.wrap(.{ .func = func_index })); | ||
| 4749 | |||
| 4365 | var comptime_mutable_decls = std.ArrayList(Decl.Index).init(gpa); | 4750 | var comptime_mutable_decls = std.ArrayList(Decl.Index).init(gpa); |
| 4366 | defer comptime_mutable_decls.deinit(); | 4751 | defer comptime_mutable_decls.deinit(); |
| 4367 | 4752 | ||
| ... | @@ -4633,7 +5018,6 @@ pub fn allocateNewDecl( | ... | @@ -4633,7 +5018,6 @@ pub fn allocateNewDecl( |
| 4633 | .analysis = .unreferenced, | 5018 | .analysis = .unreferenced, |
| 4634 | .zir_decl_index = .none, | 5019 | .zir_decl_index = .none, |
| 4635 | .src_scope = src_scope, | 5020 | .src_scope = src_scope, |
| 4636 | .generation = 0, | ||
| 4637 | .is_pub = false, | 5021 | .is_pub = false, |
| 4638 | .is_exported = false, | 5022 | .is_exported = false, |
| 4639 | .alive = false, | 5023 | .alive = false, |
| ... | @@ -4711,7 +5095,6 @@ pub fn initNewAnonDecl( | ... | @@ -4711,7 +5095,6 @@ pub fn initNewAnonDecl( |
| 4711 | new_decl.@"linksection" = .none; | 5095 | new_decl.@"linksection" = .none; |
| 4712 | new_decl.has_tv = true; | 5096 | new_decl.has_tv = true; |
| 4713 | new_decl.analysis = .complete; | 5097 | new_decl.analysis = .complete; |
| 4714 | new_decl.generation = mod.generation; | ||
| 4715 | } | 5098 | } |
| 4716 | 5099 | ||
| 4717 | pub fn errNoteNonLazy( | 5100 | pub fn errNoteNonLazy( |
| ... | @@ -5373,7 +5756,8 @@ pub fn linkerUpdateDecl(zcu: *Zcu, decl_index: Decl.Index) !void { | ... | @@ -5373,7 +5756,8 @@ pub fn linkerUpdateDecl(zcu: *Zcu, decl_index: Decl.Index) !void { |
| 5373 | "unable to codegen: {s}", | 5756 | "unable to codegen: {s}", |
| 5374 | .{@errorName(err)}, | 5757 | .{@errorName(err)}, |
| 5375 | )); | 5758 | )); |
| 5376 | decl.analysis = .codegen_failure_retryable; | 5759 | decl.analysis = .codegen_failure; |
| 5760 | try zcu.retryable_failures.append(zcu.gpa, InternPool.Depender.wrap(.{ .decl = decl_index })); | ||
| 5377 | }, | 5761 | }, |
| 5378 | }; | 5762 | }; |
| 5379 | } else if (zcu.llvm_object) |llvm_object| { | 5763 | } else if (zcu.llvm_object) |llvm_object| { |
src/Sema.zig+94-22| ... | @@ -2583,7 +2583,6 @@ fn failWithOwnedErrorMsg(sema: *Sema, block: ?*Block, err_msg: *Module.ErrorMsg) | ... | @@ -2583,7 +2583,6 @@ fn failWithOwnedErrorMsg(sema: *Sema, block: ?*Block, err_msg: *Module.ErrorMsg) |
| 2583 | ip.funcAnalysis(sema.owner_func_index).state = .sema_failure; | 2583 | ip.funcAnalysis(sema.owner_func_index).state = .sema_failure; |
| 2584 | } else { | 2584 | } else { |
| 2585 | sema.owner_decl.analysis = .sema_failure; | 2585 | sema.owner_decl.analysis = .sema_failure; |
| 2586 | sema.owner_decl.generation = mod.generation; | ||
| 2587 | } | 2586 | } |
| 2588 | if (sema.func_index != .none) { | 2587 | if (sema.func_index != .none) { |
| 2589 | ip.funcAnalysis(sema.func_index).state = .sema_failure; | 2588 | ip.funcAnalysis(sema.func_index).state = .sema_failure; |
| ... | @@ -2718,7 +2717,7 @@ pub fn getStructType( | ... | @@ -2718,7 +2717,7 @@ pub fn getStructType( |
| 2718 | assert(extended.opcode == .struct_decl); | 2717 | assert(extended.opcode == .struct_decl); |
| 2719 | const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small); | 2718 | const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small); |
| 2720 | 2719 | ||
| 2721 | var extra_index: usize = extended.operand; | 2720 | var extra_index: usize = extended.operand + @typeInfo(Zir.Inst.StructDecl).Struct.fields.len; |
| 2722 | extra_index += @intFromBool(small.has_src_node); | 2721 | extra_index += @intFromBool(small.has_src_node); |
| 2723 | const fields_len = if (small.has_fields_len) blk: { | 2722 | const fields_len = if (small.has_fields_len) blk: { |
| 2724 | const fields_len = sema.code.extra[extra_index]; | 2723 | const fields_len = sema.code.extra[extra_index]; |
| ... | @@ -2748,7 +2747,7 @@ pub fn getStructType( | ... | @@ -2748,7 +2747,7 @@ pub fn getStructType( |
| 2748 | const ty = try ip.getStructType(gpa, .{ | 2747 | const ty = try ip.getStructType(gpa, .{ |
| 2749 | .decl = decl, | 2748 | .decl = decl, |
| 2750 | .namespace = namespace.toOptional(), | 2749 | .namespace = namespace.toOptional(), |
| 2751 | .zir_index = tracked_inst, | 2750 | .zir_index = tracked_inst.toOptional(), |
| 2752 | .layout = small.layout, | 2751 | .layout = small.layout, |
| 2753 | .known_non_opv = small.known_non_opv, | 2752 | .known_non_opv = small.known_non_opv, |
| 2754 | .is_tuple = small.is_tuple, | 2753 | .is_tuple = small.is_tuple, |
| ... | @@ -2773,7 +2772,7 @@ fn zirStructDecl( | ... | @@ -2773,7 +2772,7 @@ fn zirStructDecl( |
| 2773 | const ip = &mod.intern_pool; | 2772 | const ip = &mod.intern_pool; |
| 2774 | const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small); | 2773 | const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small); |
| 2775 | const src: LazySrcLoc = if (small.has_src_node) blk: { | 2774 | const src: LazySrcLoc = if (small.has_src_node) blk: { |
| 2776 | const node_offset: i32 = @bitCast(sema.code.extra[extended.operand]); | 2775 | const node_offset: i32 = @bitCast(sema.code.extra[extended.operand + @typeInfo(Zir.Inst.StructDecl).Struct.fields.len]); |
| 2777 | break :blk LazySrcLoc.nodeOffset(node_offset); | 2776 | break :blk LazySrcLoc.nodeOffset(node_offset); |
| 2778 | } else sema.src; | 2777 | } else sema.src; |
| 2779 | 2778 | ||
| ... | @@ -2789,6 +2788,14 @@ fn zirStructDecl( | ... | @@ -2789,6 +2788,14 @@ fn zirStructDecl( |
| 2789 | new_decl.owns_tv = true; | 2788 | new_decl.owns_tv = true; |
| 2790 | errdefer mod.abortAnonDecl(new_decl_index); | 2789 | errdefer mod.abortAnonDecl(new_decl_index); |
| 2791 | 2790 | ||
| 2791 | if (sema.mod.comp.debug_incremental) { | ||
| 2792 | try ip.addDependency( | ||
| 2793 | sema.gpa, | ||
| 2794 | InternPool.Depender.wrap(.{ .decl = new_decl_index }), | ||
| 2795 | .{ .src_hash = try ip.trackZir(sema.gpa, block.getFileScope(mod), inst) }, | ||
| 2796 | ); | ||
| 2797 | } | ||
| 2798 | |||
| 2792 | const new_namespace_index = try mod.createNamespace(.{ | 2799 | const new_namespace_index = try mod.createNamespace(.{ |
| 2793 | .parent = block.namespace.toOptional(), | 2800 | .parent = block.namespace.toOptional(), |
| 2794 | .ty = undefined, | 2801 | .ty = undefined, |
| ... | @@ -2927,7 +2934,7 @@ fn zirEnumDecl( | ... | @@ -2927,7 +2934,7 @@ fn zirEnumDecl( |
| 2927 | const mod = sema.mod; | 2934 | const mod = sema.mod; |
| 2928 | const gpa = sema.gpa; | 2935 | const gpa = sema.gpa; |
| 2929 | const small: Zir.Inst.EnumDecl.Small = @bitCast(extended.small); | 2936 | const small: Zir.Inst.EnumDecl.Small = @bitCast(extended.small); |
| 2930 | var extra_index: usize = extended.operand; | 2937 | var extra_index: usize = extended.operand + @typeInfo(Zir.Inst.EnumDecl).Struct.fields.len; |
| 2931 | 2938 | ||
| 2932 | const src: LazySrcLoc = if (small.has_src_node) blk: { | 2939 | const src: LazySrcLoc = if (small.has_src_node) blk: { |
| 2933 | const node_offset: i32 = @bitCast(sema.code.extra[extra_index]); | 2940 | const node_offset: i32 = @bitCast(sema.code.extra[extra_index]); |
| ... | @@ -2973,6 +2980,14 @@ fn zirEnumDecl( | ... | @@ -2973,6 +2980,14 @@ fn zirEnumDecl( |
| 2973 | new_decl.owns_tv = true; | 2980 | new_decl.owns_tv = true; |
| 2974 | errdefer if (!done) mod.abortAnonDecl(new_decl_index); | 2981 | errdefer if (!done) mod.abortAnonDecl(new_decl_index); |
| 2975 | 2982 | ||
| 2983 | if (sema.mod.comp.debug_incremental) { | ||
| 2984 | try mod.intern_pool.addDependency( | ||
| 2985 | sema.gpa, | ||
| 2986 | InternPool.Depender.wrap(.{ .decl = new_decl_index }), | ||
| 2987 | .{ .src_hash = try mod.intern_pool.trackZir(sema.gpa, block.getFileScope(mod), inst) }, | ||
| 2988 | ); | ||
| 2989 | } | ||
| 2990 | |||
| 2976 | const new_namespace_index = try mod.createNamespace(.{ | 2991 | const new_namespace_index = try mod.createNamespace(.{ |
| 2977 | .parent = block.namespace.toOptional(), | 2992 | .parent = block.namespace.toOptional(), |
| 2978 | .ty = undefined, | 2993 | .ty = undefined, |
| ... | @@ -3008,6 +3023,7 @@ fn zirEnumDecl( | ... | @@ -3008,6 +3023,7 @@ fn zirEnumDecl( |
| 3008 | .auto | 3023 | .auto |
| 3009 | else | 3024 | else |
| 3010 | .explicit, | 3025 | .explicit, |
| 3026 | .zir_index = (try mod.intern_pool.trackZir(sema.gpa, block.getFileScope(mod), inst)).toOptional(), | ||
| 3011 | }); | 3027 | }); |
| 3012 | if (sema.builtin_type_target_index != .none) { | 3028 | if (sema.builtin_type_target_index != .none) { |
| 3013 | mod.intern_pool.resolveBuiltinType(sema.builtin_type_target_index, incomplete_enum.index); | 3029 | mod.intern_pool.resolveBuiltinType(sema.builtin_type_target_index, incomplete_enum.index); |
| ... | @@ -3191,7 +3207,7 @@ fn zirUnionDecl( | ... | @@ -3191,7 +3207,7 @@ fn zirUnionDecl( |
| 3191 | const mod = sema.mod; | 3207 | const mod = sema.mod; |
| 3192 | const gpa = sema.gpa; | 3208 | const gpa = sema.gpa; |
| 3193 | const small: Zir.Inst.UnionDecl.Small = @bitCast(extended.small); | 3209 | const small: Zir.Inst.UnionDecl.Small = @bitCast(extended.small); |
| 3194 | var extra_index: usize = extended.operand; | 3210 | var extra_index: usize = extended.operand + @typeInfo(Zir.Inst.UnionDecl).Struct.fields.len; |
| 3195 | 3211 | ||
| 3196 | const src: LazySrcLoc = if (small.has_src_node) blk: { | 3212 | const src: LazySrcLoc = if (small.has_src_node) blk: { |
| 3197 | const node_offset: i32 = @bitCast(sema.code.extra[extra_index]); | 3213 | const node_offset: i32 = @bitCast(sema.code.extra[extra_index]); |
| ... | @@ -3225,6 +3241,14 @@ fn zirUnionDecl( | ... | @@ -3225,6 +3241,14 @@ fn zirUnionDecl( |
| 3225 | new_decl.owns_tv = true; | 3241 | new_decl.owns_tv = true; |
| 3226 | errdefer mod.abortAnonDecl(new_decl_index); | 3242 | errdefer mod.abortAnonDecl(new_decl_index); |
| 3227 | 3243 | ||
| 3244 | if (sema.mod.comp.debug_incremental) { | ||
| 3245 | try mod.intern_pool.addDependency( | ||
| 3246 | sema.gpa, | ||
| 3247 | InternPool.Depender.wrap(.{ .decl = new_decl_index }), | ||
| 3248 | .{ .src_hash = try mod.intern_pool.trackZir(sema.gpa, block.getFileScope(mod), inst) }, | ||
| 3249 | ); | ||
| 3250 | } | ||
| 3251 | |||
| 3228 | const new_namespace_index = try mod.createNamespace(.{ | 3252 | const new_namespace_index = try mod.createNamespace(.{ |
| 3229 | .parent = block.namespace.toOptional(), | 3253 | .parent = block.namespace.toOptional(), |
| 3230 | .ty = undefined, | 3254 | .ty = undefined, |
| ... | @@ -3254,7 +3278,7 @@ fn zirUnionDecl( | ... | @@ -3254,7 +3278,7 @@ fn zirUnionDecl( |
| 3254 | }, | 3278 | }, |
| 3255 | .decl = new_decl_index, | 3279 | .decl = new_decl_index, |
| 3256 | .namespace = new_namespace_index, | 3280 | .namespace = new_namespace_index, |
| 3257 | .zir_index = try mod.intern_pool.trackZir(gpa, block.getFileScope(mod), inst), | 3281 | .zir_index = (try mod.intern_pool.trackZir(gpa, block.getFileScope(mod), inst)).toOptional(), |
| 3258 | .fields_len = fields_len, | 3282 | .fields_len = fields_len, |
| 3259 | .enum_tag_ty = .none, | 3283 | .enum_tag_ty = .none, |
| 3260 | .field_types = &.{}, | 3284 | .field_types = &.{}, |
| ... | @@ -3318,6 +3342,14 @@ fn zirOpaqueDecl( | ... | @@ -3318,6 +3342,14 @@ fn zirOpaqueDecl( |
| 3318 | new_decl.owns_tv = true; | 3342 | new_decl.owns_tv = true; |
| 3319 | errdefer mod.abortAnonDecl(new_decl_index); | 3343 | errdefer mod.abortAnonDecl(new_decl_index); |
| 3320 | 3344 | ||
| 3345 | if (sema.mod.comp.debug_incremental) { | ||
| 3346 | try mod.intern_pool.addDependency( | ||
| 3347 | sema.gpa, | ||
| 3348 | InternPool.Depender.wrap(.{ .decl = new_decl_index }), | ||
| 3349 | .{ .src_hash = try mod.intern_pool.trackZir(sema.gpa, block.getFileScope(mod), inst) }, | ||
| 3350 | ); | ||
| 3351 | } | ||
| 3352 | |||
| 3321 | const new_namespace_index = try mod.createNamespace(.{ | 3353 | const new_namespace_index = try mod.createNamespace(.{ |
| 3322 | .parent = block.namespace.toOptional(), | 3354 | .parent = block.namespace.toOptional(), |
| 3323 | .ty = undefined, | 3355 | .ty = undefined, |
| ... | @@ -3329,6 +3361,7 @@ fn zirOpaqueDecl( | ... | @@ -3329,6 +3361,7 @@ fn zirOpaqueDecl( |
| 3329 | const opaque_ty = try mod.intern(.{ .opaque_type = .{ | 3361 | const opaque_ty = try mod.intern(.{ .opaque_type = .{ |
| 3330 | .decl = new_decl_index, | 3362 | .decl = new_decl_index, |
| 3331 | .namespace = new_namespace_index, | 3363 | .namespace = new_namespace_index, |
| 3364 | .zir_index = (try mod.intern_pool.trackZir(sema.gpa, block.getFileScope(mod), inst)).toOptional(), | ||
| 3332 | } }); | 3365 | } }); |
| 3333 | // TODO: figure out InternPool removals for incremental compilation | 3366 | // TODO: figure out InternPool removals for incremental compilation |
| 3334 | //errdefer mod.intern_pool.remove(opaque_ty); | 3367 | //errdefer mod.intern_pool.remove(opaque_ty); |
| ... | @@ -7890,6 +7923,8 @@ fn instantiateGenericCall( | ... | @@ -7890,6 +7923,8 @@ fn instantiateGenericCall( |
| 7890 | const generic_owner_func = mod.intern_pool.indexToKey(generic_owner).func; | 7923 | const generic_owner_func = mod.intern_pool.indexToKey(generic_owner).func; |
| 7891 | const generic_owner_ty_info = mod.typeToFunc(Type.fromInterned(generic_owner_func.ty)).?; | 7924 | const generic_owner_ty_info = mod.typeToFunc(Type.fromInterned(generic_owner_func.ty)).?; |
| 7892 | 7925 | ||
| 7926 | try sema.declareDependency(.{ .src_hash = generic_owner_func.zir_body_inst }); | ||
| 7927 | |||
| 7893 | // Even though there may already be a generic instantiation corresponding | 7928 | // Even though there may already be a generic instantiation corresponding |
| 7894 | // to this callsite, we must evaluate the expressions of the generic | 7929 | // to this callsite, we must evaluate the expressions of the generic |
| 7895 | // function signature with the values of the callsite plugged in. | 7930 | // function signature with the values of the callsite plugged in. |
| ... | @@ -9440,7 +9475,6 @@ fn funcCommon( | ... | @@ -9440,7 +9475,6 @@ fn funcCommon( |
| 9440 | .inferred_error_set = inferred_error_set, | 9475 | .inferred_error_set = inferred_error_set, |
| 9441 | .generic_owner = sema.generic_owner, | 9476 | .generic_owner = sema.generic_owner, |
| 9442 | .comptime_args = sema.comptime_args, | 9477 | .comptime_args = sema.comptime_args, |
| 9443 | .generation = mod.generation, | ||
| 9444 | }); | 9478 | }); |
| 9445 | return finishFunc( | 9479 | return finishFunc( |
| 9446 | sema, | 9480 | sema, |
| ... | @@ -13598,6 +13632,12 @@ fn zirHasDecl(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air | ... | @@ -13598,6 +13632,12 @@ fn zirHasDecl(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 13598 | }); | 13632 | }); |
| 13599 | 13633 | ||
| 13600 | try sema.checkNamespaceType(block, lhs_src, container_type); | 13634 | try sema.checkNamespaceType(block, lhs_src, container_type); |
| 13635 | if (container_type.typeDeclInst(mod)) |type_decl_inst| { | ||
| 13636 | try sema.declareDependency(.{ .namespace_name = .{ | ||
| 13637 | .namespace = type_decl_inst, | ||
| 13638 | .name = decl_name, | ||
| 13639 | } }); | ||
| 13640 | } | ||
| 13601 | 13641 | ||
| 13602 | const namespace = container_type.getNamespaceIndex(mod).unwrap() orelse | 13642 | const namespace = container_type.getNamespaceIndex(mod).unwrap() orelse |
| 13603 | return .bool_false; | 13643 | return .bool_false; |
| ... | @@ -17451,6 +17491,10 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -17451,6 +17491,10 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 17451 | const type_info_ty = try sema.getBuiltinType("Type"); | 17491 | const type_info_ty = try sema.getBuiltinType("Type"); |
| 17452 | const type_info_tag_ty = type_info_ty.unionTagType(mod).?; | 17492 | const type_info_tag_ty = type_info_ty.unionTagType(mod).?; |
| 17453 | 17493 | ||
| 17494 | if (ty.typeDeclInst(mod)) |type_decl_inst| { | ||
| 17495 | try sema.declareDependency(.{ .namespace = type_decl_inst }); | ||
| 17496 | } | ||
| 17497 | |||
| 17454 | switch (ty.zigTypeTag(mod)) { | 17498 | switch (ty.zigTypeTag(mod)) { |
| 17455 | .Type, | 17499 | .Type, |
| 17456 | .Void, | 17500 | .Void, |
| ... | @@ -21318,6 +21362,7 @@ fn zirReify( | ... | @@ -21318,6 +21362,7 @@ fn zirReify( |
| 21318 | else | 21362 | else |
| 21319 | .explicit, | 21363 | .explicit, |
| 21320 | .tag_ty = int_tag_ty.toIntern(), | 21364 | .tag_ty = int_tag_ty.toIntern(), |
| 21365 | .zir_index = .none, | ||
| 21321 | }); | 21366 | }); |
| 21322 | // TODO: figure out InternPool removals for incremental compilation | 21367 | // TODO: figure out InternPool removals for incremental compilation |
| 21323 | //errdefer ip.remove(incomplete_enum.index); | 21368 | //errdefer ip.remove(incomplete_enum.index); |
| ... | @@ -21415,6 +21460,7 @@ fn zirReify( | ... | @@ -21415,6 +21460,7 @@ fn zirReify( |
| 21415 | const opaque_ty = try mod.intern(.{ .opaque_type = .{ | 21460 | const opaque_ty = try mod.intern(.{ .opaque_type = .{ |
| 21416 | .decl = new_decl_index, | 21461 | .decl = new_decl_index, |
| 21417 | .namespace = new_namespace_index, | 21462 | .namespace = new_namespace_index, |
| 21463 | .zir_index = .none, | ||
| 21418 | } }); | 21464 | } }); |
| 21419 | // TODO: figure out InternPool removals for incremental compilation | 21465 | // TODO: figure out InternPool removals for incremental compilation |
| 21420 | //errdefer ip.remove(opaque_ty); | 21466 | //errdefer ip.remove(opaque_ty); |
| ... | @@ -21633,7 +21679,7 @@ fn zirReify( | ... | @@ -21633,7 +21679,7 @@ fn zirReify( |
| 21633 | .namespace = new_namespace_index, | 21679 | .namespace = new_namespace_index, |
| 21634 | .enum_tag_ty = enum_tag_ty, | 21680 | .enum_tag_ty = enum_tag_ty, |
| 21635 | .fields_len = fields_len, | 21681 | .fields_len = fields_len, |
| 21636 | .zir_index = try ip.trackZir(gpa, block.getFileScope(mod), inst), // TODO: should reified types be handled differently? | 21682 | .zir_index = .none, |
| 21637 | .flags = .{ | 21683 | .flags = .{ |
| 21638 | .layout = layout, | 21684 | .layout = layout, |
| 21639 | .status = .have_field_types, | 21685 | .status = .have_field_types, |
| ... | @@ -21801,7 +21847,7 @@ fn reifyStruct( | ... | @@ -21801,7 +21847,7 @@ fn reifyStruct( |
| 21801 | const ty = try ip.getStructType(gpa, .{ | 21847 | const ty = try ip.getStructType(gpa, .{ |
| 21802 | .decl = new_decl_index, | 21848 | .decl = new_decl_index, |
| 21803 | .namespace = .none, | 21849 | .namespace = .none, |
| 21804 | .zir_index = try mod.intern_pool.trackZir(gpa, block.getFileScope(mod), inst), // TODO: should reified types be handled differently? | 21850 | .zir_index = .none, |
| 21805 | .layout = layout, | 21851 | .layout = layout, |
| 21806 | .known_non_opv = false, | 21852 | .known_non_opv = false, |
| 21807 | .fields_len = fields_len, | 21853 | .fields_len = fields_len, |
| ... | @@ -25922,7 +25968,6 @@ fn zirBuiltinExtern( | ... | @@ -25922,7 +25968,6 @@ fn zirBuiltinExtern( |
| 25922 | new_decl.has_tv = true; | 25968 | new_decl.has_tv = true; |
| 25923 | new_decl.owns_tv = true; | 25969 | new_decl.owns_tv = true; |
| 25924 | new_decl.analysis = .complete; | 25970 | new_decl.analysis = .complete; |
| 25925 | new_decl.generation = mod.generation; | ||
| 25926 | 25971 | ||
| 25927 | try sema.ensureDeclAnalyzed(new_decl_index); | 25972 | try sema.ensureDeclAnalyzed(new_decl_index); |
| 25928 | 25973 | ||
| ... | @@ -26421,6 +26466,7 @@ fn prepareSimplePanic(sema: *Sema, block: *Block) !void { | ... | @@ -26421,6 +26466,7 @@ fn prepareSimplePanic(sema: *Sema, block: *Block) !void { |
| 26421 | // owns the function. | 26466 | // owns the function. |
| 26422 | try sema.ensureDeclAnalyzed(decl_index); | 26467 | try sema.ensureDeclAnalyzed(decl_index); |
| 26423 | const tv = try mod.declPtr(decl_index).typedValue(); | 26468 | const tv = try mod.declPtr(decl_index).typedValue(); |
| 26469 | try sema.declareDependency(.{ .decl_val = decl_index }); | ||
| 26424 | assert(tv.ty.zigTypeTag(mod) == .Fn); | 26470 | assert(tv.ty.zigTypeTag(mod) == .Fn); |
| 26425 | assert(try sema.fnHasRuntimeBits(tv.ty)); | 26471 | assert(try sema.fnHasRuntimeBits(tv.ty)); |
| 26426 | const func_index = tv.val.toIntern(); | 26472 | const func_index = tv.val.toIntern(); |
| ... | @@ -26842,6 +26888,13 @@ fn fieldVal( | ... | @@ -26842,6 +26888,13 @@ fn fieldVal( |
| 26842 | const val = (try sema.resolveDefinedValue(block, object_src, dereffed_type)).?; | 26888 | const val = (try sema.resolveDefinedValue(block, object_src, dereffed_type)).?; |
| 26843 | const child_type = val.toType(); | 26889 | const child_type = val.toType(); |
| 26844 | 26890 | ||
| 26891 | if (child_type.typeDeclInst(mod)) |type_decl_inst| { | ||
| 26892 | try sema.declareDependency(.{ .namespace_name = .{ | ||
| 26893 | .namespace = type_decl_inst, | ||
| 26894 | .name = field_name, | ||
| 26895 | } }); | ||
| 26896 | } | ||
| 26897 | |||
| 26845 | switch (try child_type.zigTypeTagOrPoison(mod)) { | 26898 | switch (try child_type.zigTypeTagOrPoison(mod)) { |
| 26846 | .ErrorSet => { | 26899 | .ErrorSet => { |
| 26847 | switch (ip.indexToKey(child_type.toIntern())) { | 26900 | switch (ip.indexToKey(child_type.toIntern())) { |
| ... | @@ -27065,6 +27118,13 @@ fn fieldPtr( | ... | @@ -27065,6 +27118,13 @@ fn fieldPtr( |
| 27065 | const val = (sema.resolveDefinedValue(block, src, inner) catch unreachable).?; | 27118 | const val = (sema.resolveDefinedValue(block, src, inner) catch unreachable).?; |
| 27066 | const child_type = val.toType(); | 27119 | const child_type = val.toType(); |
| 27067 | 27120 | ||
| 27121 | if (child_type.typeDeclInst(mod)) |type_decl_inst| { | ||
| 27122 | try sema.declareDependency(.{ .namespace_name = .{ | ||
| 27123 | .namespace = type_decl_inst, | ||
| 27124 | .name = field_name, | ||
| 27125 | } }); | ||
| 27126 | } | ||
| 27127 | |||
| 27068 | switch (child_type.zigTypeTag(mod)) { | 27128 | switch (child_type.zigTypeTag(mod)) { |
| 27069 | .ErrorSet => { | 27129 | .ErrorSet => { |
| 27070 | switch (ip.indexToKey(child_type.toIntern())) { | 27130 | switch (ip.indexToKey(child_type.toIntern())) { |
| ... | @@ -31134,6 +31194,7 @@ fn beginComptimePtrLoad( | ... | @@ -31134,6 +31194,7 @@ fn beginComptimePtrLoad( |
| 31134 | const is_mutable = ptr.addr == .mut_decl; | 31194 | const is_mutable = ptr.addr == .mut_decl; |
| 31135 | const decl = mod.declPtr(decl_index); | 31195 | const decl = mod.declPtr(decl_index); |
| 31136 | const decl_tv = try decl.typedValue(); | 31196 | const decl_tv = try decl.typedValue(); |
| 31197 | try sema.declareDependency(.{ .decl_val = decl_index }); | ||
| 31137 | if (decl.val.getVariable(mod) != null) return error.RuntimeLoad; | 31198 | if (decl.val.getVariable(mod) != null) return error.RuntimeLoad; |
| 31138 | 31199 | ||
| 31139 | const layout_defined = decl.ty.hasWellDefinedLayout(mod); | 31200 | const layout_defined = decl.ty.hasWellDefinedLayout(mod); |
| ... | @@ -32387,6 +32448,8 @@ fn analyzeDeclRefInner(sema: *Sema, decl_index: InternPool.DeclIndex, analyze_fn | ... | @@ -32387,6 +32448,8 @@ fn analyzeDeclRefInner(sema: *Sema, decl_index: InternPool.DeclIndex, analyze_fn |
| 32387 | 32448 | ||
| 32388 | const decl = mod.declPtr(decl_index); | 32449 | const decl = mod.declPtr(decl_index); |
| 32389 | const decl_tv = try decl.typedValue(); | 32450 | const decl_tv = try decl.typedValue(); |
| 32451 | // TODO: if this is a `decl_ref` of a non-variable decl, only depend on decl type | ||
| 32452 | try sema.declareDependency(.{ .decl_val = decl_index }); | ||
| 32390 | const ptr_ty = try sema.ptrType(.{ | 32453 | const ptr_ty = try sema.ptrType(.{ |
| 32391 | .child = decl_tv.ty.toIntern(), | 32454 | .child = decl_tv.ty.toIntern(), |
| 32392 | .flags = .{ | 32455 | .flags = .{ |
| ... | @@ -35683,13 +35746,13 @@ fn semaBackingIntType(mod: *Module, struct_type: InternPool.Key.StructType) Comp | ... | @@ -35683,13 +35746,13 @@ fn semaBackingIntType(mod: *Module, struct_type: InternPool.Key.StructType) Comp |
| 35683 | break :blk accumulator; | 35746 | break :blk accumulator; |
| 35684 | }; | 35747 | }; |
| 35685 | 35748 | ||
| 35686 | const zir_index = struct_type.zir_index.resolve(ip); | 35749 | const zir_index = struct_type.zir_index.unwrap().?.resolve(ip); |
| 35687 | const extended = zir.instructions.items(.data)[@intFromEnum(zir_index)].extended; | 35750 | const extended = zir.instructions.items(.data)[@intFromEnum(zir_index)].extended; |
| 35688 | assert(extended.opcode == .struct_decl); | 35751 | assert(extended.opcode == .struct_decl); |
| 35689 | const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small); | 35752 | const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small); |
| 35690 | 35753 | ||
| 35691 | if (small.has_backing_int) { | 35754 | if (small.has_backing_int) { |
| 35692 | var extra_index: usize = extended.operand; | 35755 | var extra_index: usize = extended.operand + @typeInfo(Zir.Inst.StructDecl).Struct.fields.len; |
| 35693 | extra_index += @intFromBool(small.has_src_node); | 35756 | extra_index += @intFromBool(small.has_src_node); |
| 35694 | extra_index += @intFromBool(small.has_fields_len); | 35757 | extra_index += @intFromBool(small.has_fields_len); |
| 35695 | extra_index += @intFromBool(small.has_decls_len); | 35758 | extra_index += @intFromBool(small.has_decls_len); |
| ... | @@ -36162,10 +36225,8 @@ pub fn resolveTypeFieldsStruct( | ... | @@ -36162,10 +36225,8 @@ pub fn resolveTypeFieldsStruct( |
| 36162 | .file_failure, | 36225 | .file_failure, |
| 36163 | .dependency_failure, | 36226 | .dependency_failure, |
| 36164 | .sema_failure, | 36227 | .sema_failure, |
| 36165 | .sema_failure_retryable, | ||
| 36166 | => { | 36228 | => { |
| 36167 | sema.owner_decl.analysis = .dependency_failure; | 36229 | sema.owner_decl.analysis = .dependency_failure; |
| 36168 | sema.owner_decl.generation = mod.generation; | ||
| 36169 | return error.AnalysisFail; | 36230 | return error.AnalysisFail; |
| 36170 | }, | 36231 | }, |
| 36171 | else => {}, | 36232 | else => {}, |
| ... | @@ -36221,10 +36282,8 @@ pub fn resolveTypeFieldsUnion(sema: *Sema, ty: Type, union_type: InternPool.Key. | ... | @@ -36221,10 +36282,8 @@ pub fn resolveTypeFieldsUnion(sema: *Sema, ty: Type, union_type: InternPool.Key. |
| 36221 | .file_failure, | 36282 | .file_failure, |
| 36222 | .dependency_failure, | 36283 | .dependency_failure, |
| 36223 | .sema_failure, | 36284 | .sema_failure, |
| 36224 | .sema_failure_retryable, | ||
| 36225 | => { | 36285 | => { |
| 36226 | sema.owner_decl.analysis = .dependency_failure; | 36286 | sema.owner_decl.analysis = .dependency_failure; |
| 36227 | sema.owner_decl.generation = mod.generation; | ||
| 36228 | return error.AnalysisFail; | 36287 | return error.AnalysisFail; |
| 36229 | }, | 36288 | }, |
| 36230 | else => {}, | 36289 | else => {}, |
| ... | @@ -36404,7 +36463,7 @@ fn structZirInfo(zir: Zir, zir_index: Zir.Inst.Index) struct { | ... | @@ -36404,7 +36463,7 @@ fn structZirInfo(zir: Zir, zir_index: Zir.Inst.Index) struct { |
| 36404 | const extended = zir.instructions.items(.data)[@intFromEnum(zir_index)].extended; | 36463 | const extended = zir.instructions.items(.data)[@intFromEnum(zir_index)].extended; |
| 36405 | assert(extended.opcode == .struct_decl); | 36464 | assert(extended.opcode == .struct_decl); |
| 36406 | const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small); | 36465 | const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small); |
| 36407 | var extra_index: usize = extended.operand; | 36466 | var extra_index: usize = extended.operand + @typeInfo(Zir.Inst.StructDecl).Struct.fields.len; |
| 36408 | 36467 | ||
| 36409 | extra_index += @intFromBool(small.has_src_node); | 36468 | extra_index += @intFromBool(small.has_src_node); |
| 36410 | 36469 | ||
| ... | @@ -36448,7 +36507,7 @@ fn semaStructFields( | ... | @@ -36448,7 +36507,7 @@ fn semaStructFields( |
| 36448 | const decl = mod.declPtr(decl_index); | 36507 | const decl = mod.declPtr(decl_index); |
| 36449 | const namespace_index = struct_type.namespace.unwrap() orelse decl.src_namespace; | 36508 | const namespace_index = struct_type.namespace.unwrap() orelse decl.src_namespace; |
| 36450 | const zir = mod.namespacePtr(namespace_index).file_scope.zir; | 36509 | const zir = mod.namespacePtr(namespace_index).file_scope.zir; |
| 36451 | const zir_index = struct_type.zir_index.resolve(ip); | 36510 | const zir_index = struct_type.zir_index.unwrap().?.resolve(ip); |
| 36452 | 36511 | ||
| 36453 | const fields_len, const small, var extra_index = structZirInfo(zir, zir_index); | 36512 | const fields_len, const small, var extra_index = structZirInfo(zir, zir_index); |
| 36454 | 36513 | ||
| ... | @@ -36719,7 +36778,7 @@ fn semaStructFieldInits( | ... | @@ -36719,7 +36778,7 @@ fn semaStructFieldInits( |
| 36719 | const decl = mod.declPtr(decl_index); | 36778 | const decl = mod.declPtr(decl_index); |
| 36720 | const namespace_index = struct_type.namespace.unwrap() orelse decl.src_namespace; | 36779 | const namespace_index = struct_type.namespace.unwrap() orelse decl.src_namespace; |
| 36721 | const zir = mod.namespacePtr(namespace_index).file_scope.zir; | 36780 | const zir = mod.namespacePtr(namespace_index).file_scope.zir; |
| 36722 | const zir_index = struct_type.zir_index.resolve(ip); | 36781 | const zir_index = struct_type.zir_index.unwrap().?.resolve(ip); |
| 36723 | const fields_len, const small, var extra_index = structZirInfo(zir, zir_index); | 36782 | const fields_len, const small, var extra_index = structZirInfo(zir, zir_index); |
| 36724 | 36783 | ||
| 36725 | var comptime_mutable_decls = std.ArrayList(InternPool.DeclIndex).init(gpa); | 36784 | var comptime_mutable_decls = std.ArrayList(InternPool.DeclIndex).init(gpa); |
| ... | @@ -36868,11 +36927,11 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Key.Un | ... | @@ -36868,11 +36927,11 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Key.Un |
| 36868 | const ip = &mod.intern_pool; | 36927 | const ip = &mod.intern_pool; |
| 36869 | const decl_index = union_type.decl; | 36928 | const decl_index = union_type.decl; |
| 36870 | const zir = mod.namespacePtr(union_type.namespace).file_scope.zir; | 36929 | const zir = mod.namespacePtr(union_type.namespace).file_scope.zir; |
| 36871 | const zir_index = union_type.zir_index.resolve(ip); | 36930 | const zir_index = union_type.zir_index.unwrap().?.resolve(ip); |
| 36872 | const extended = zir.instructions.items(.data)[@intFromEnum(zir_index)].extended; | 36931 | const extended = zir.instructions.items(.data)[@intFromEnum(zir_index)].extended; |
| 36873 | assert(extended.opcode == .union_decl); | 36932 | assert(extended.opcode == .union_decl); |
| 36874 | const small: Zir.Inst.UnionDecl.Small = @bitCast(extended.small); | 36933 | const small: Zir.Inst.UnionDecl.Small = @bitCast(extended.small); |
| 36875 | var extra_index: usize = extended.operand; | 36934 | var extra_index: usize = extended.operand + @typeInfo(Zir.Inst.UnionDecl).Struct.fields.len; |
| 36876 | 36935 | ||
| 36877 | const src = LazySrcLoc.nodeOffset(0); | 36936 | const src = LazySrcLoc.nodeOffset(0); |
| 36878 | extra_index += @intFromBool(small.has_src_node); | 36937 | extra_index += @intFromBool(small.has_src_node); |
| ... | @@ -37312,6 +37371,7 @@ fn generateUnionTagTypeNumbered( | ... | @@ -37312,6 +37371,7 @@ fn generateUnionTagTypeNumbered( |
| 37312 | .names = enum_field_names, | 37371 | .names = enum_field_names, |
| 37313 | .values = enum_field_vals, | 37372 | .values = enum_field_vals, |
| 37314 | .tag_mode = .explicit, | 37373 | .tag_mode = .explicit, |
| 37374 | .zir_index = .none, | ||
| 37315 | }); | 37375 | }); |
| 37316 | 37376 | ||
| 37317 | new_decl.ty = Type.type; | 37377 | new_decl.ty = Type.type; |
| ... | @@ -37362,6 +37422,7 @@ fn generateUnionTagTypeSimple( | ... | @@ -37362,6 +37422,7 @@ fn generateUnionTagTypeSimple( |
| 37362 | .names = enum_field_names, | 37422 | .names = enum_field_names, |
| 37363 | .values = &.{}, | 37423 | .values = &.{}, |
| 37364 | .tag_mode = .auto, | 37424 | .tag_mode = .auto, |
| 37425 | .zir_index = .none, | ||
| 37365 | }); | 37426 | }); |
| 37366 | 37427 | ||
| 37367 | const new_decl = mod.declPtr(new_decl_index); | 37428 | const new_decl = mod.declPtr(new_decl_index); |
| ... | @@ -38876,3 +38937,14 @@ fn ptrType(sema: *Sema, info: InternPool.Key.PtrType) CompileError!Type { | ... | @@ -38876,3 +38937,14 @@ fn ptrType(sema: *Sema, info: InternPool.Key.PtrType) CompileError!Type { |
| 38876 | } | 38937 | } |
| 38877 | return sema.mod.ptrType(info); | 38938 | return sema.mod.ptrType(info); |
| 38878 | } | 38939 | } |
| 38940 | |||
| 38941 | pub fn declareDependency(sema: *Sema, dependee: InternPool.Dependee) !void { | ||
| 38942 | if (!sema.mod.comp.debug_incremental) return; | ||
| 38943 | const depender = InternPool.Depender.wrap( | ||
| 38944 | if (sema.owner_func_index != .none) | ||
| 38945 | .{ .func = sema.owner_func_index } | ||
| 38946 | else | ||
| 38947 | .{ .decl = sema.owner_decl_index }, | ||
| 38948 | ); | ||
| 38949 | try sema.mod.intern_pool.addDependency(sema.gpa, depender, dependee); | ||
| 38950 | } |
src/Zir.zig+131-3| ... | @@ -2497,6 +2497,7 @@ pub const Inst = struct { | ... | @@ -2497,6 +2497,7 @@ pub const Inst = struct { |
| 2497 | /// } | 2497 | /// } |
| 2498 | /// 2. body: Index // for each body_len | 2498 | /// 2. body: Index // for each body_len |
| 2499 | /// 3. src_locs: SrcLocs // if body_len != 0 | 2499 | /// 3. src_locs: SrcLocs // if body_len != 0 |
| 2500 | /// 4. proto_hash: std.zig.SrcHash // if body_len != 0; hash of function prototype | ||
| 2500 | pub const Func = struct { | 2501 | pub const Func = struct { |
| 2501 | /// If this is 0 it means a void return type. | 2502 | /// If this is 0 it means a void return type. |
| 2502 | /// If this is 1 it means return_type is a simple Ref | 2503 | /// If this is 1 it means return_type is a simple Ref |
| ... | @@ -2558,6 +2559,7 @@ pub const Inst = struct { | ... | @@ -2558,6 +2559,7 @@ pub const Inst = struct { |
| 2558 | /// - each bit starting with LSB corresponds to parameter indexes | 2559 | /// - each bit starting with LSB corresponds to parameter indexes |
| 2559 | /// 17. body: Index // for each body_len | 2560 | /// 17. body: Index // for each body_len |
| 2560 | /// 18. src_locs: Func.SrcLocs // if body_len != 0 | 2561 | /// 18. src_locs: Func.SrcLocs // if body_len != 0 |
| 2562 | /// 19. proto_hash: std.zig.SrcHash // if body_len != 0; hash of function prototype | ||
| 2561 | pub const FuncFancy = struct { | 2563 | pub const FuncFancy = struct { |
| 2562 | /// Points to the block that contains the param instructions for this function. | 2564 | /// Points to the block that contains the param instructions for this function. |
| 2563 | /// If this is a `declaration`, it refers to the declaration's value body. | 2565 | /// If this is a `declaration`, it refers to the declaration's value body. |
| ... | @@ -3040,6 +3042,12 @@ pub const Inst = struct { | ... | @@ -3040,6 +3042,12 @@ pub const Inst = struct { |
| 3040 | /// init_body_inst: Inst, // for each init_body_len | 3042 | /// init_body_inst: Inst, // for each init_body_len |
| 3041 | /// } | 3043 | /// } |
| 3042 | pub const StructDecl = struct { | 3044 | pub const StructDecl = struct { |
| 3045 | // These fields should be concatenated and reinterpreted as a `std.zig.SrcHash`. | ||
| 3046 | // This hash contains the source of all fields, and any specified attributes (`extern`, backing type, etc). | ||
| 3047 | fields_hash_0: u32, | ||
| 3048 | fields_hash_1: u32, | ||
| 3049 | fields_hash_2: u32, | ||
| 3050 | fields_hash_3: u32, | ||
| 3043 | pub const Small = packed struct { | 3051 | pub const Small = packed struct { |
| 3044 | has_src_node: bool, | 3052 | has_src_node: bool, |
| 3045 | has_fields_len: bool, | 3053 | has_fields_len: bool, |
| ... | @@ -3102,6 +3110,12 @@ pub const Inst = struct { | ... | @@ -3102,6 +3110,12 @@ pub const Inst = struct { |
| 3102 | /// value: Ref, // if corresponding bit is set | 3110 | /// value: Ref, // if corresponding bit is set |
| 3103 | /// } | 3111 | /// } |
| 3104 | pub const EnumDecl = struct { | 3112 | pub const EnumDecl = struct { |
| 3113 | // These fields should be concatenated and reinterpreted as a `std.zig.SrcHash`. | ||
| 3114 | // This hash contains the source of all fields, and the backing type if specified. | ||
| 3115 | fields_hash_0: u32, | ||
| 3116 | fields_hash_1: u32, | ||
| 3117 | fields_hash_2: u32, | ||
| 3118 | fields_hash_3: u32, | ||
| 3105 | pub const Small = packed struct { | 3119 | pub const Small = packed struct { |
| 3106 | has_src_node: bool, | 3120 | has_src_node: bool, |
| 3107 | has_tag_type: bool, | 3121 | has_tag_type: bool, |
| ... | @@ -3137,6 +3151,12 @@ pub const Inst = struct { | ... | @@ -3137,6 +3151,12 @@ pub const Inst = struct { |
| 3137 | /// tag_value: Ref, // if corresponding bit is set | 3151 | /// tag_value: Ref, // if corresponding bit is set |
| 3138 | /// } | 3152 | /// } |
| 3139 | pub const UnionDecl = struct { | 3153 | pub const UnionDecl = struct { |
| 3154 | // These fields should be concatenated and reinterpreted as a `std.zig.SrcHash`. | ||
| 3155 | // This hash contains the source of all fields, and any specified attributes (`extern` etc). | ||
| 3156 | fields_hash_0: u32, | ||
| 3157 | fields_hash_1: u32, | ||
| 3158 | fields_hash_2: u32, | ||
| 3159 | fields_hash_3: u32, | ||
| 3140 | pub const Small = packed struct { | 3160 | pub const Small = packed struct { |
| 3141 | has_src_node: bool, | 3161 | has_src_node: bool, |
| 3142 | has_tag_type: bool, | 3162 | has_tag_type: bool, |
| ... | @@ -3455,7 +3475,7 @@ pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator { | ... | @@ -3455,7 +3475,7 @@ pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator { |
| 3455 | switch (extended.opcode) { | 3475 | switch (extended.opcode) { |
| 3456 | .struct_decl => { | 3476 | .struct_decl => { |
| 3457 | const small: Inst.StructDecl.Small = @bitCast(extended.small); | 3477 | const small: Inst.StructDecl.Small = @bitCast(extended.small); |
| 3458 | var extra_index: u32 = extended.operand; | 3478 | var extra_index: u32 = @intCast(extended.operand + @typeInfo(Inst.StructDecl).Struct.fields.len); |
| 3459 | extra_index += @intFromBool(small.has_src_node); | 3479 | extra_index += @intFromBool(small.has_src_node); |
| 3460 | extra_index += @intFromBool(small.has_fields_len); | 3480 | extra_index += @intFromBool(small.has_fields_len); |
| 3461 | const decls_len = if (small.has_decls_len) decls_len: { | 3481 | const decls_len = if (small.has_decls_len) decls_len: { |
| ... | @@ -3482,7 +3502,7 @@ pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator { | ... | @@ -3482,7 +3502,7 @@ pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator { |
| 3482 | }, | 3502 | }, |
| 3483 | .enum_decl => { | 3503 | .enum_decl => { |
| 3484 | const small: Inst.EnumDecl.Small = @bitCast(extended.small); | 3504 | const small: Inst.EnumDecl.Small = @bitCast(extended.small); |
| 3485 | var extra_index: u32 = extended.operand; | 3505 | var extra_index: u32 = @intCast(extended.operand + @typeInfo(Inst.EnumDecl).Struct.fields.len); |
| 3486 | extra_index += @intFromBool(small.has_src_node); | 3506 | extra_index += @intFromBool(small.has_src_node); |
| 3487 | extra_index += @intFromBool(small.has_tag_type); | 3507 | extra_index += @intFromBool(small.has_tag_type); |
| 3488 | extra_index += @intFromBool(small.has_body_len); | 3508 | extra_index += @intFromBool(small.has_body_len); |
| ... | @@ -3501,7 +3521,7 @@ pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator { | ... | @@ -3501,7 +3521,7 @@ pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator { |
| 3501 | }, | 3521 | }, |
| 3502 | .union_decl => { | 3522 | .union_decl => { |
| 3503 | const small: Inst.UnionDecl.Small = @bitCast(extended.small); | 3523 | const small: Inst.UnionDecl.Small = @bitCast(extended.small); |
| 3504 | var extra_index: u32 = extended.operand; | 3524 | var extra_index: u32 = @intCast(extended.operand + @typeInfo(Inst.UnionDecl).Struct.fields.len); |
| 3505 | extra_index += @intFromBool(small.has_src_node); | 3525 | extra_index += @intFromBool(small.has_src_node); |
| 3506 | extra_index += @intFromBool(small.has_tag_type); | 3526 | extra_index += @intFromBool(small.has_tag_type); |
| 3507 | extra_index += @intFromBool(small.has_body_len); | 3527 | extra_index += @intFromBool(small.has_body_len); |
| ... | @@ -3938,3 +3958,111 @@ pub fn getDeclaration(zir: Zir, inst: Zir.Inst.Index) struct { Inst.Declaration, | ... | @@ -3938,3 +3958,111 @@ pub fn getDeclaration(zir: Zir, inst: Zir.Inst.Index) struct { Inst.Declaration, |
| 3938 | @intCast(extra.end), | 3958 | @intCast(extra.end), |
| 3939 | }; | 3959 | }; |
| 3940 | } | 3960 | } |
| 3961 | |||
| 3962 | pub fn getAssociatedSrcHash(zir: Zir, inst: Zir.Inst.Index) ?std.zig.SrcHash { | ||
| 3963 | const tag = zir.instructions.items(.tag); | ||
| 3964 | const data = zir.instructions.items(.data); | ||
| 3965 | switch (tag[@intFromEnum(inst)]) { | ||
| 3966 | .declaration => { | ||
| 3967 | const pl_node = data[@intFromEnum(inst)].pl_node; | ||
| 3968 | const extra = zir.extraData(Inst.Declaration, pl_node.payload_index); | ||
| 3969 | return @bitCast([4]u32{ | ||
| 3970 | extra.data.src_hash_0, | ||
| 3971 | extra.data.src_hash_1, | ||
| 3972 | extra.data.src_hash_2, | ||
| 3973 | extra.data.src_hash_3, | ||
| 3974 | }); | ||
| 3975 | }, | ||
| 3976 | .func, .func_inferred => { | ||
| 3977 | const pl_node = data[@intFromEnum(inst)].pl_node; | ||
| 3978 | const extra = zir.extraData(Inst.Func, pl_node.payload_index); | ||
| 3979 | if (extra.data.body_len == 0) { | ||
| 3980 | // Function type or extern fn - no associated hash | ||
| 3981 | return null; | ||
| 3982 | } | ||
| 3983 | const extra_index = extra.end + | ||
| 3984 | 1 + | ||
| 3985 | extra.data.body_len + | ||
| 3986 | @typeInfo(Inst.Func.SrcLocs).Struct.fields.len; | ||
| 3987 | return @bitCast([4]u32{ | ||
| 3988 | zir.extra[extra_index + 0], | ||
| 3989 | zir.extra[extra_index + 1], | ||
| 3990 | zir.extra[extra_index + 2], | ||
| 3991 | zir.extra[extra_index + 3], | ||
| 3992 | }); | ||
| 3993 | }, | ||
| 3994 | .func_fancy => { | ||
| 3995 | const pl_node = data[@intFromEnum(inst)].pl_node; | ||
| 3996 | const extra = zir.extraData(Inst.FuncFancy, pl_node.payload_index); | ||
| 3997 | if (extra.data.body_len == 0) { | ||
| 3998 | // Function type or extern fn - no associated hash | ||
| 3999 | return null; | ||
| 4000 | } | ||
| 4001 | const bits = extra.data.bits; | ||
| 4002 | var extra_index = extra.end; | ||
| 4003 | extra_index += @intFromBool(bits.has_lib_name); | ||
| 4004 | if (bits.has_align_body) { | ||
| 4005 | const body_len = zir.extra[extra_index]; | ||
| 4006 | extra_index += 1 + body_len; | ||
| 4007 | } else extra_index += @intFromBool(bits.has_align_ref); | ||
| 4008 | if (bits.has_addrspace_body) { | ||
| 4009 | const body_len = zir.extra[extra_index]; | ||
| 4010 | extra_index += 1 + body_len; | ||
| 4011 | } else extra_index += @intFromBool(bits.has_addrspace_ref); | ||
| 4012 | if (bits.has_section_body) { | ||
| 4013 | const body_len = zir.extra[extra_index]; | ||
| 4014 | extra_index += 1 + body_len; | ||
| 4015 | } else extra_index += @intFromBool(bits.has_section_ref); | ||
| 4016 | if (bits.has_cc_body) { | ||
| 4017 | const body_len = zir.extra[extra_index]; | ||
| 4018 | extra_index += 1 + body_len; | ||
| 4019 | } else extra_index += @intFromBool(bits.has_cc_ref); | ||
| 4020 | if (bits.has_ret_ty_body) { | ||
| 4021 | const body_len = zir.extra[extra_index]; | ||
| 4022 | extra_index += 1 + body_len; | ||
| 4023 | } else extra_index += @intFromBool(bits.has_ret_ty_ref); | ||
| 4024 | extra_index += @intFromBool(bits.has_any_noalias); | ||
| 4025 | extra_index += extra.data.body_len; | ||
| 4026 | extra_index += @typeInfo(Zir.Inst.Func.SrcLocs).Struct.fields.len; | ||
| 4027 | return @bitCast([4]u32{ | ||
| 4028 | zir.extra[extra_index + 0], | ||
| 4029 | zir.extra[extra_index + 1], | ||
| 4030 | zir.extra[extra_index + 2], | ||
| 4031 | zir.extra[extra_index + 3], | ||
| 4032 | }); | ||
| 4033 | }, | ||
| 4034 | .extended => {}, | ||
| 4035 | else => return null, | ||
| 4036 | } | ||
| 4037 | const extended = data[@intFromEnum(inst)].extended; | ||
| 4038 | switch (extended.opcode) { | ||
| 4039 | .struct_decl => { | ||
| 4040 | const extra = zir.extraData(Inst.StructDecl, extended.operand).data; | ||
| 4041 | return @bitCast([4]u32{ | ||
| 4042 | extra.fields_hash_0, | ||
| 4043 | extra.fields_hash_1, | ||
| 4044 | extra.fields_hash_2, | ||
| 4045 | extra.fields_hash_3, | ||
| 4046 | }); | ||
| 4047 | }, | ||
| 4048 | .union_decl => { | ||
| 4049 | const extra = zir.extraData(Inst.UnionDecl, extended.operand).data; | ||
| 4050 | return @bitCast([4]u32{ | ||
| 4051 | extra.fields_hash_0, | ||
| 4052 | extra.fields_hash_1, | ||
| 4053 | extra.fields_hash_2, | ||
| 4054 | extra.fields_hash_3, | ||
| 4055 | }); | ||
| 4056 | }, | ||
| 4057 | .enum_decl => { | ||
| 4058 | const extra = zir.extraData(Inst.EnumDecl, extended.operand).data; | ||
| 4059 | return @bitCast([4]u32{ | ||
| 4060 | extra.fields_hash_0, | ||
| 4061 | extra.fields_hash_1, | ||
| 4062 | extra.fields_hash_2, | ||
| 4063 | extra.fields_hash_3, | ||
| 4064 | }); | ||
| 4065 | }, | ||
| 4066 | else => return null, | ||
| 4067 | } | ||
| 4068 | } |
src/main.zig+1| ... | @@ -3255,6 +3255,7 @@ fn buildOutputType( | ... | @@ -3255,6 +3255,7 @@ fn buildOutputType( |
| 3255 | .cache_mode = cache_mode, | 3255 | .cache_mode = cache_mode, |
| 3256 | .subsystem = subsystem, | 3256 | .subsystem = subsystem, |
| 3257 | .debug_compile_errors = debug_compile_errors, | 3257 | .debug_compile_errors = debug_compile_errors, |
| 3258 | .debug_incremental = debug_incremental, | ||
| 3258 | .enable_link_snapshots = enable_link_snapshots, | 3259 | .enable_link_snapshots = enable_link_snapshots, |
| 3259 | .install_name = install_name, | 3260 | .install_name = install_name, |
| 3260 | .entitlements = entitlements, | 3261 | .entitlements = entitlements, |
src/print_zir.zig+34-3| ... | @@ -1401,7 +1401,17 @@ const Writer = struct { | ... | @@ -1401,7 +1401,17 @@ const Writer = struct { |
| 1401 | fn writeStructDecl(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void { | 1401 | fn writeStructDecl(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void { |
| 1402 | const small = @as(Zir.Inst.StructDecl.Small, @bitCast(extended.small)); | 1402 | const small = @as(Zir.Inst.StructDecl.Small, @bitCast(extended.small)); |
| 1403 | 1403 | ||
| 1404 | var extra_index: usize = extended.operand; | 1404 | const extra = self.code.extraData(Zir.Inst.StructDecl, extended.operand); |
| 1405 | const fields_hash: std.zig.SrcHash = @bitCast([4]u32{ | ||
| 1406 | extra.data.fields_hash_0, | ||
| 1407 | extra.data.fields_hash_1, | ||
| 1408 | extra.data.fields_hash_2, | ||
| 1409 | extra.data.fields_hash_3, | ||
| 1410 | }); | ||
| 1411 | |||
| 1412 | try stream.print("hash({}) ", .{std.fmt.fmtSliceHexLower(&fields_hash)}); | ||
| 1413 | |||
| 1414 | var extra_index: usize = extra.end; | ||
| 1405 | 1415 | ||
| 1406 | const src_node: ?i32 = if (small.has_src_node) blk: { | 1416 | const src_node: ?i32 = if (small.has_src_node) blk: { |
| 1407 | const src_node = @as(i32, @bitCast(self.code.extra[extra_index])); | 1417 | const src_node = @as(i32, @bitCast(self.code.extra[extra_index])); |
| ... | @@ -1591,7 +1601,17 @@ const Writer = struct { | ... | @@ -1591,7 +1601,17 @@ const Writer = struct { |
| 1591 | fn writeUnionDecl(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void { | 1601 | fn writeUnionDecl(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void { |
| 1592 | const small = @as(Zir.Inst.UnionDecl.Small, @bitCast(extended.small)); | 1602 | const small = @as(Zir.Inst.UnionDecl.Small, @bitCast(extended.small)); |
| 1593 | 1603 | ||
| 1594 | var extra_index: usize = extended.operand; | 1604 | const extra = self.code.extraData(Zir.Inst.UnionDecl, extended.operand); |
| 1605 | const fields_hash: std.zig.SrcHash = @bitCast([4]u32{ | ||
| 1606 | extra.data.fields_hash_0, | ||
| 1607 | extra.data.fields_hash_1, | ||
| 1608 | extra.data.fields_hash_2, | ||
| 1609 | extra.data.fields_hash_3, | ||
| 1610 | }); | ||
| 1611 | |||
| 1612 | try stream.print("hash({}) ", .{std.fmt.fmtSliceHexLower(&fields_hash)}); | ||
| 1613 | |||
| 1614 | var extra_index: usize = extra.end; | ||
| 1595 | 1615 | ||
| 1596 | const src_node: ?i32 = if (small.has_src_node) blk: { | 1616 | const src_node: ?i32 = if (small.has_src_node) blk: { |
| 1597 | const src_node = @as(i32, @bitCast(self.code.extra[extra_index])); | 1617 | const src_node = @as(i32, @bitCast(self.code.extra[extra_index])); |
| ... | @@ -1733,7 +1753,18 @@ const Writer = struct { | ... | @@ -1733,7 +1753,18 @@ const Writer = struct { |
| 1733 | 1753 | ||
| 1734 | fn writeEnumDecl(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void { | 1754 | fn writeEnumDecl(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void { |
| 1735 | const small = @as(Zir.Inst.EnumDecl.Small, @bitCast(extended.small)); | 1755 | const small = @as(Zir.Inst.EnumDecl.Small, @bitCast(extended.small)); |
| 1736 | var extra_index: usize = extended.operand; | 1756 | |
| 1757 | const extra = self.code.extraData(Zir.Inst.EnumDecl, extended.operand); | ||
| 1758 | const fields_hash: std.zig.SrcHash = @bitCast([4]u32{ | ||
| 1759 | extra.data.fields_hash_0, | ||
| 1760 | extra.data.fields_hash_1, | ||
| 1761 | extra.data.fields_hash_2, | ||
| 1762 | extra.data.fields_hash_3, | ||
| 1763 | }); | ||
| 1764 | |||
| 1765 | try stream.print("hash({}) ", .{std.fmt.fmtSliceHexLower(&fields_hash)}); | ||
| 1766 | |||
| 1767 | var extra_index: usize = extra.end; | ||
| 1737 | 1768 | ||
| 1738 | const src_node: ?i32 = if (small.has_src_node) blk: { | 1769 | const src_node: ?i32 = if (small.has_src_node) blk: { |
| 1739 | const src_node = @as(i32, @bitCast(self.code.extra[extra_index])); | 1770 | const src_node = @as(i32, @bitCast(self.code.extra[extra_index])); |
src/type.zig+12| ... | @@ -4,6 +4,7 @@ const Value = @import("Value.zig"); | ... | @@ -4,6 +4,7 @@ const Value = @import("Value.zig"); |
| 4 | const assert = std.debug.assert; | 4 | const assert = std.debug.assert; |
| 5 | const Target = std.Target; | 5 | const Target = std.Target; |
| 6 | const Module = @import("Module.zig"); | 6 | const Module = @import("Module.zig"); |
| 7 | const Zcu = Module; | ||
| 7 | const log = std.log.scoped(.Type); | 8 | const log = std.log.scoped(.Type); |
| 8 | const target_util = @import("target.zig"); | 9 | const target_util = @import("target.zig"); |
| 9 | const TypedValue = @import("TypedValue.zig"); | 10 | const TypedValue = @import("TypedValue.zig"); |
| ... | @@ -3228,6 +3229,17 @@ pub const Type = struct { | ... | @@ -3228,6 +3229,17 @@ pub const Type = struct { |
| 3228 | }; | 3229 | }; |
| 3229 | } | 3230 | } |
| 3230 | 3231 | ||
| 3232 | pub fn typeDeclInst(ty: Type, zcu: *const Zcu) ?InternPool.TrackedInst.Index { | ||
| 3233 | return switch (zcu.intern_pool.indexToKey(ty.toIntern())) { | ||
| 3234 | inline .struct_type, | ||
| 3235 | .union_type, | ||
| 3236 | .enum_type, | ||
| 3237 | .opaque_type, | ||
| 3238 | => |info| info.zir_index.unwrap(), | ||
| 3239 | else => null, | ||
| 3240 | }; | ||
| 3241 | } | ||
| 3242 | |||
| 3231 | pub const @"u1": Type = .{ .ip_index = .u1_type }; | 3243 | pub const @"u1": Type = .{ .ip_index = .u1_type }; |
| 3232 | pub const @"u8": Type = .{ .ip_index = .u8_type }; | 3244 | pub const @"u8": Type = .{ .ip_index = .u8_type }; |
| 3233 | pub const @"u16": Type = .{ .ip_index = .u16_type }; | 3245 | pub const @"u16": Type = .{ .ip_index = .u16_type }; |