authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-01-26 15:51:33-08:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2024-01-26 15:51:33-08:00
logb96fb858c88b97617e6fa0e3c6966a8e900caf7f
treee1729e12109e85e1ed2d4b7eb06187206e9bd8d3
parent8a0429e885489eac497aa97fdfcaaa1befb2b6d4
parent06d8bb32e3edfb4a26c6d3ecdf198574f4bd3f87
signaturebadge-check Signed by PGP key B5690EEEBB952194

Merge pull request #18654 from mlugg/incremental-the-second

InternPool: introduce TrackedInst to prepare for incremental compilation

9 files changed, 969 insertions(+), 1058 deletions(-)

src/AstGen.zig+225-159
...@@ -86,6 +86,7 @@ fn setExtra(astgen: *AstGen, index: usize, extra: anytype) void {...@@ -86,6 +86,7 @@ fn setExtra(astgen: *AstGen, index: usize, extra: anytype) void {
8686
87 Zir.Inst.Ref,87 Zir.Inst.Ref,
88 Zir.Inst.Index,88 Zir.Inst.Index,
89 Zir.Inst.Declaration.Name,
89 Zir.NullTerminatedString,90 Zir.NullTerminatedString,
90 => @intFromEnum(@field(extra, field.name)),91 => @intFromEnum(@field(extra, field.name)),
9192
...@@ -95,6 +96,7 @@ fn setExtra(astgen: *AstGen, index: usize, extra: anytype) void {...@@ -95,6 +96,7 @@ fn setExtra(astgen: *AstGen, index: usize, extra: anytype) void {
95 Zir.Inst.SwitchBlock.Bits,96 Zir.Inst.SwitchBlock.Bits,
96 Zir.Inst.SwitchBlockErrUnion.Bits,97 Zir.Inst.SwitchBlockErrUnion.Bits,
97 Zir.Inst.FuncFancy.Bits,98 Zir.Inst.FuncFancy.Bits,
99 Zir.Inst.Declaration.Flags,
98 => @bitCast(@field(extra, field.name)),100 => @bitCast(@field(extra, field.name)),
99101
100 else => @compileError("bad field type"),102 else => @compileError("bad field type"),
...@@ -132,8 +134,8 @@ pub fn generate(gpa: Allocator, tree: Ast) Allocator.Error!Zir {...@@ -132,8 +134,8 @@ pub fn generate(gpa: Allocator, tree: Ast) Allocator.Error!Zir {
132 };134 };
133 defer astgen.deinit(gpa);135 defer astgen.deinit(gpa);
134136
135 // String table indexes 0, 1, 2 are reserved for special meaning.137 // String table index 0 is reserved for `NullTerminatedString.empty`.
136 try astgen.string_bytes.appendSlice(gpa, &[_]u8{ 0, 0, 0 });138 try astgen.string_bytes.append(gpa, 0);
137139
138 // We expect at least as many ZIR instructions and extra data items140 // We expect at least as many ZIR instructions and extra data items
139 // as AST nodes.141 // as AST nodes.
...@@ -355,8 +357,13 @@ const ResultInfo = struct {...@@ -355,8 +357,13 @@ const ResultInfo = struct {
355 };357 };
356};358};
357359
360/// TODO: modify Sema to remove in favour of `coerced_align_ri`
358const align_ri: ResultInfo = .{ .rl = .{ .ty = .u29_type } };361const align_ri: ResultInfo = .{ .rl = .{ .ty = .u29_type } };
359const coerced_align_ri: ResultInfo = .{ .rl = .{ .coerced_ty = .u29_type } };362const coerced_align_ri: ResultInfo = .{ .rl = .{ .coerced_ty = .u29_type } };
363/// TODO: modify Sema to remove in favour of `coerced_addrspace_ri`
364const addrspace_ri: ResultInfo = .{ .rl = .{ .ty = .address_space_type } };
365const coerced_addrspace_ri: ResultInfo = .{ .rl = .{ .coerced_ty = .address_space_type } };
366const coerced_linksection_ri: ResultInfo = .{ .rl = .{ .coerced_ty = .slice_const_u8_type } };
360const bool_ri: ResultInfo = .{ .rl = .{ .ty = .bool_type } };367const bool_ri: ResultInfo = .{ .rl = .{ .ty = .bool_type } };
361const type_ri: ResultInfo = .{ .rl = .{ .ty = .type_type } };368const type_ri: ResultInfo = .{ .rl = .{ .ty = .type_type } };
362const coerced_type_ri: ResultInfo = .{ .rl = .{ .coerced_ty = .type_type } };369const coerced_type_ri: ResultInfo = .{ .rl = .{ .coerced_ty = .type_type } };
...@@ -2592,6 +2599,7 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As...@@ -2592,6 +2599,7 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As
2592 .block,2599 .block,
2593 .block_comptime,2600 .block_comptime,
2594 .block_inline,2601 .block_inline,
2602 .declaration,
2595 .suspend_block,2603 .suspend_block,
2596 .loop,2604 .loop,
2597 .bool_br_and,2605 .bool_br_and,
...@@ -3783,7 +3791,7 @@ fn ptrType(...@@ -3783,7 +3791,7 @@ fn ptrType(
3783 gz.astgen.source_line = source_line;3791 gz.astgen.source_line = source_line;
3784 gz.astgen.source_column = source_column;3792 gz.astgen.source_column = source_column;
37853793
3786 addrspace_ref = try expr(gz, scope, .{ .rl = .{ .ty = .address_space_type } }, ptr_info.ast.addrspace_node);3794 addrspace_ref = try expr(gz, scope, addrspace_ri, ptr_info.ast.addrspace_node);
3787 trailing_count += 1;3795 trailing_count += 1;
3788 }3796 }
3789 if (ptr_info.ast.align_node != 0) {3797 if (ptr_info.ast.align_node != 0) {
...@@ -3899,8 +3907,6 @@ fn arrayTypeSentinel(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node....@@ -3899,8 +3907,6 @@ fn arrayTypeSentinel(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.
3899const WipMembers = struct {3907const WipMembers = struct {
3900 payload: *ArrayListUnmanaged(u32),3908 payload: *ArrayListUnmanaged(u32),
3901 payload_top: usize,3909 payload_top: usize,
3902 decls_start: u32,
3903 decls_end: u32,
3904 field_bits_start: u32,3910 field_bits_start: u32,
3905 fields_start: u32,3911 fields_start: u32,
3906 fields_end: u32,3912 fields_end: u32,
...@@ -3908,43 +3914,27 @@ const WipMembers = struct {...@@ -3908,43 +3914,27 @@ const WipMembers = struct {
3908 field_index: u32 = 0,3914 field_index: u32 = 0,
39093915
3910 const Self = @This();3916 const Self = @This();
3911 /// struct, union, enum, and opaque decls all use same 4 bits per decl
3912 const bits_per_decl = 4;
3913 const decls_per_u32 = 32 / bits_per_decl;
3914 /// struct, union, enum, and opaque decls all have maximum size of 11 u32 slots
3915 /// (4 for src_hash + line + name + value + doc_comment + align + link_section + address_space )
3916 const max_decl_size = 11;
39173917
3918 fn init(gpa: Allocator, payload: *ArrayListUnmanaged(u32), decl_count: u32, field_count: u32, comptime bits_per_field: u32, comptime max_field_size: u32) Allocator.Error!Self {3918 fn init(gpa: Allocator, payload: *ArrayListUnmanaged(u32), decl_count: u32, field_count: u32, comptime bits_per_field: u32, comptime max_field_size: u32) Allocator.Error!Self {
3919 const payload_top: u32 = @intCast(payload.items.len);3919 const payload_top: u32 = @intCast(payload.items.len);
3920 const decls_start = payload_top + (decl_count + decls_per_u32 - 1) / decls_per_u32;3920 const field_bits_start = payload_top + decl_count;
3921 const field_bits_start = decls_start + decl_count * max_decl_size;
3922 const fields_start = field_bits_start + if (bits_per_field > 0) blk: {3921 const fields_start = field_bits_start + if (bits_per_field > 0) blk: {
3923 const fields_per_u32 = 32 / bits_per_field;3922 const fields_per_u32 = 32 / bits_per_field;
3924 break :blk (field_count + fields_per_u32 - 1) / fields_per_u32;3923 break :blk (field_count + fields_per_u32 - 1) / fields_per_u32;
3925 } else 0;3924 } else 0;
3926 const payload_end = fields_start + field_count * max_field_size;3925 const payload_end = fields_start + field_count * max_field_size;
3927 try payload.resize(gpa, payload_end);3926 try payload.resize(gpa, payload_end);
3928 return Self{3927 return .{
3929 .payload = payload,3928 .payload = payload,
3930 .payload_top = payload_top,3929 .payload_top = payload_top,
3931 .decls_start = decls_start,
3932 .field_bits_start = field_bits_start,3930 .field_bits_start = field_bits_start,
3933 .fields_start = fields_start,3931 .fields_start = fields_start,
3934 .decls_end = decls_start,
3935 .fields_end = fields_start,3932 .fields_end = fields_start,
3936 };3933 };
3937 }3934 }
39383935
3939 fn nextDecl(self: *Self, is_pub: bool, is_export: bool, has_align: bool, has_section_or_addrspace: bool) void {3936 fn nextDecl(self: *Self, decl_inst: Zir.Inst.Index) void {
3940 const index = self.payload_top + self.decl_index / decls_per_u32;3937 self.payload.items[self.payload_top + self.decl_index] = @intFromEnum(decl_inst);
3941 assert(index < self.decls_start);
3942 const bit_bag: u32 = if (self.decl_index % decls_per_u32 == 0) 0 else self.payload.items[index];
3943 self.payload.items[index] = (bit_bag >> bits_per_decl) |
3944 (@as(u32, @intFromBool(is_pub)) << 28) |
3945 (@as(u32, @intFromBool(is_export)) << 29) |
3946 (@as(u32, @intFromBool(has_align)) << 30) |
3947 (@as(u32, @intFromBool(has_section_or_addrspace)) << 31);
3948 self.decl_index += 1;3938 self.decl_index += 1;
3949 }3939 }
39503940
...@@ -3962,18 +3952,6 @@ const WipMembers = struct {...@@ -3962,18 +3952,6 @@ const WipMembers = struct {
3962 self.field_index += 1;3952 self.field_index += 1;
3963 }3953 }
39643954
3965 fn appendToDecl(self: *Self, data: u32) void {
3966 assert(self.decls_end < self.field_bits_start);
3967 self.payload.items[self.decls_end] = data;
3968 self.decls_end += 1;
3969 }
3970
3971 fn appendToDeclSlice(self: *Self, data: []const u32) void {
3972 assert(self.decls_end + data.len <= self.field_bits_start);
3973 @memcpy(self.payload.items[self.decls_end..][0..data.len], data);
3974 self.decls_end += @intCast(data.len);
3975 }
3976
3977 fn appendToField(self: *Self, data: u32) void {3955 fn appendToField(self: *Self, data: u32) void {
3978 assert(self.fields_end < self.payload.items.len);3956 assert(self.fields_end < self.payload.items.len);
3979 self.payload.items[self.fields_end] = data;3957 self.payload.items[self.fields_end] = data;
...@@ -3981,11 +3959,6 @@ const WipMembers = struct {...@@ -3981,11 +3959,6 @@ const WipMembers = struct {
3981 }3959 }
39823960
3983 fn finishBits(self: *Self, comptime bits_per_field: u32) void {3961 fn finishBits(self: *Self, comptime bits_per_field: u32) void {
3984 const empty_decl_slots = decls_per_u32 - (self.decl_index % decls_per_u32);
3985 if (self.decl_index > 0 and empty_decl_slots < decls_per_u32) {
3986 const index = self.payload_top + self.decl_index / decls_per_u32;
3987 self.payload.items[index] >>= @intCast(empty_decl_slots * bits_per_decl);
3988 }
3989 if (bits_per_field > 0) {3962 if (bits_per_field > 0) {
3990 const fields_per_u32 = 32 / bits_per_field;3963 const fields_per_u32 = 32 / bits_per_field;
3991 const empty_field_slots = fields_per_u32 - (self.field_index % fields_per_u32);3964 const empty_field_slots = fields_per_u32 - (self.field_index % fields_per_u32);
...@@ -3997,7 +3970,7 @@ const WipMembers = struct {...@@ -3997,7 +3970,7 @@ const WipMembers = struct {
3997 }3970 }
39983971
3999 fn declsSlice(self: *Self) []u32 {3972 fn declsSlice(self: *Self) []u32 {
4000 return self.payload.items[self.payload_top..self.decls_end];3973 return self.payload.items[self.payload_top..][0..self.decl_index];
4001 }3974 }
40023975
4003 fn fieldsSlice(self: *Self) []u32 {3976 fn fieldsSlice(self: *Self) []u32 {
...@@ -4023,11 +3996,10 @@ fn fnDecl(...@@ -4023,11 +3996,10 @@ fn fnDecl(
40233996
4024 // missing function name already happened in scanDecls()3997 // missing function name already happened in scanDecls()
4025 const fn_name_token = fn_proto.name_token orelse return error.AnalysisFail;3998 const fn_name_token = fn_proto.name_token orelse return error.AnalysisFail;
4026 const fn_name_str_index = try astgen.identAsString(fn_name_token);
40273999
4028 // We insert this at the beginning so that its instruction index marks the4000 // We insert this at the beginning so that its instruction index marks the
4029 // start of the top level declaration.4001 // start of the top level declaration.
4030 const block_inst = try gz.makeBlockInst(.block_inline, fn_proto.ast.proto_node);4002 const decl_inst = try gz.makeBlockInst(.declaration, fn_proto.ast.proto_node);
4031 astgen.advanceSourceCursorToNode(decl_node);4003 astgen.advanceSourceCursorToNode(decl_node);
40324004
4033 var decl_gz: GenZir = .{4005 var decl_gz: GenZir = .{
...@@ -4072,8 +4044,7 @@ fn fnDecl(...@@ -4072,8 +4044,7 @@ fn fnDecl(
40724044
4073 const doc_comment_index = try astgen.docCommentAsString(fn_proto.firstToken());4045 const doc_comment_index = try astgen.docCommentAsString(fn_proto.firstToken());
40744046
4075 // align, linksection, and addrspace is passed in the func instruction in this case.4047 wip_members.nextDecl(decl_inst);
4076 wip_members.nextDecl(is_pub, is_export, false, false);
40774048
4078 var noalias_bits: u32 = 0;4049 var noalias_bits: u32 = 0;
4079 var params_scope = &fn_gz.base;4050 var params_scope = &fn_gz.base;
...@@ -4213,7 +4184,7 @@ fn fnDecl(...@@ -4213,7 +4184,7 @@ fn fnDecl(
4213 var addrspace_gz = decl_gz.makeSubBlock(params_scope);4184 var addrspace_gz = decl_gz.makeSubBlock(params_scope);
4214 defer addrspace_gz.unstack();4185 defer addrspace_gz.unstack();
4215 const addrspace_ref: Zir.Inst.Ref = if (fn_proto.ast.addrspace_expr == 0) .none else inst: {4186 const addrspace_ref: Zir.Inst.Ref = if (fn_proto.ast.addrspace_expr == 0) .none else inst: {
4216 const inst = try expr(&decl_gz, params_scope, .{ .rl = .{ .coerced_ty = .address_space_type } }, fn_proto.ast.addrspace_expr);4187 const inst = try expr(&decl_gz, params_scope, addrspace_ri, fn_proto.ast.addrspace_expr);
4217 if (addrspace_gz.instructionsSlice().len == 0) {4188 if (addrspace_gz.instructionsSlice().len == 0) {
4218 // In this case we will send a len=0 body which can be encoded more efficiently.4189 // In this case we will send a len=0 body which can be encoded more efficiently.
4219 break :inst inst;4190 break :inst inst;
...@@ -4298,7 +4269,7 @@ fn fnDecl(...@@ -4298,7 +4269,7 @@ fn fnDecl(
4298 .section_gz = &section_gz,4269 .section_gz = &section_gz,
4299 .addrspace_ref = addrspace_ref,4270 .addrspace_ref = addrspace_ref,
4300 .addrspace_gz = &addrspace_gz,4271 .addrspace_gz = &addrspace_gz,
4301 .param_block = block_inst,4272 .param_block = decl_inst,
4302 .body_gz = null,4273 .body_gz = null,
4303 .lib_name = lib_name,4274 .lib_name = lib_name,
4304 .is_var_args = is_var_args,4275 .is_var_args = is_var_args,
...@@ -4349,7 +4320,7 @@ fn fnDecl(...@@ -4349,7 +4320,7 @@ fn fnDecl(
4349 .addrspace_gz = &addrspace_gz,4320 .addrspace_gz = &addrspace_gz,
4350 .lbrace_line = lbrace_line,4321 .lbrace_line = lbrace_line,
4351 .lbrace_column = lbrace_column,4322 .lbrace_column = lbrace_column,
4352 .param_block = block_inst,4323 .param_block = decl_inst,
4353 .body_gz = &fn_gz,4324 .body_gz = &fn_gz,
4354 .lib_name = lib_name,4325 .lib_name = lib_name,
4355 .is_var_args = is_var_args,4326 .is_var_args = is_var_args,
...@@ -4363,20 +4334,21 @@ fn fnDecl(...@@ -4363,20 +4334,21 @@ fn fnDecl(
43634334
4364 // We add this at the end so that its instruction index marks the end range4335 // We add this at the end so that its instruction index marks the end range
4365 // of the top level declaration. addFunc already unstacked fn_gz and ret_gz.4336 // of the top level declaration. addFunc already unstacked fn_gz and ret_gz.
4366 _ = try decl_gz.addBreak(.break_inline, block_inst, func_inst);4337 _ = try decl_gz.addBreak(.break_inline, decl_inst, func_inst);
4367 try decl_gz.setBlockBody(block_inst);4338
43684339 try setDeclaration(
4369 {4340 decl_inst,
4370 const contents_hash align(@alignOf(u32)) = std.zig.hashSrc(tree.getNodeSource(decl_node));4341 std.zig.hashSrc(tree.getNodeSource(decl_node)),
4371 wip_members.appendToDeclSlice(std.mem.bytesAsSlice(u32, &contents_hash));4342 .{ .named = fn_name_token },
4372 }4343 decl_gz.decl_line - gz.decl_line,
4373 {4344 is_pub,
4374 const line_delta = decl_gz.decl_line - gz.decl_line;4345 is_export,
4375 wip_members.appendToDecl(line_delta);4346 doc_comment_index,
4376 }4347 &decl_gz,
4377 wip_members.appendToDecl(@intFromEnum(fn_name_str_index));4348 // align, linksection, and addrspace are passed in the func instruction in this case.
4378 wip_members.appendToDecl(@intFromEnum(block_inst));4349 // TODO: move them from the function instruction to the declaration instruction?
4379 wip_members.appendToDecl(@intFromEnum(doc_comment_index));4350 null,
4351 );
4380}4352}
43814353
4382fn globalVarDecl(4354fn globalVarDecl(
...@@ -4393,10 +4365,9 @@ fn globalVarDecl(...@@ -4393,10 +4365,9 @@ fn globalVarDecl(
4393 const is_mutable = token_tags[var_decl.ast.mut_token] == .keyword_var;4365 const is_mutable = token_tags[var_decl.ast.mut_token] == .keyword_var;
4394 // We do this at the beginning so that the instruction index marks the range start4366 // We do this at the beginning so that the instruction index marks the range start
4395 // of the top level declaration.4367 // of the top level declaration.
4396 const block_inst = try gz.makeBlockInst(.block_inline, node);4368 const decl_inst = try gz.makeBlockInst(.declaration, node);
43974369
4398 const name_token = var_decl.ast.mut_token + 1;4370 const name_token = var_decl.ast.mut_token + 1;
4399 const name_str_index = try astgen.identAsString(name_token);
4400 astgen.advanceSourceCursorToNode(node);4371 astgen.advanceSourceCursorToNode(node);
44014372
4402 var block_scope: GenZir = .{4373 var block_scope: GenZir = .{
...@@ -4420,17 +4391,7 @@ fn globalVarDecl(...@@ -4420,17 +4391,7 @@ fn globalVarDecl(
4420 const maybe_extern_token = var_decl.extern_export_token orelse break :blk false;4391 const maybe_extern_token = var_decl.extern_export_token orelse break :blk false;
4421 break :blk token_tags[maybe_extern_token] == .keyword_extern;4392 break :blk token_tags[maybe_extern_token] == .keyword_extern;
4422 };4393 };
4423 const align_inst: Zir.Inst.Ref = if (var_decl.ast.align_node == 0) .none else inst: {4394 wip_members.nextDecl(decl_inst);
4424 break :inst try expr(&block_scope, &block_scope.base, align_ri, var_decl.ast.align_node);
4425 };
4426 const addrspace_inst: Zir.Inst.Ref = if (var_decl.ast.addrspace_node == 0) .none else inst: {
4427 break :inst try expr(&block_scope, &block_scope.base, .{ .rl = .{ .ty = .address_space_type } }, var_decl.ast.addrspace_node);
4428 };
4429 const section_inst: Zir.Inst.Ref = if (var_decl.ast.section_node == 0) .none else inst: {
4430 break :inst try comptimeExpr(&block_scope, &block_scope.base, .{ .rl = .{ .ty = .slice_const_u8_type } }, var_decl.ast.section_node);
4431 };
4432 const has_section_or_addrspace = section_inst != .none or addrspace_inst != .none;
4433 wip_members.nextDecl(is_pub, is_export, align_inst != .none, has_section_or_addrspace);
44344395
4435 const is_threadlocal = if (var_decl.threadlocal_token) |tok| blk: {4396 const is_threadlocal = if (var_decl.threadlocal_token) |tok| blk: {
4436 if (!is_mutable) {4397 if (!is_mutable) {
...@@ -4513,29 +4474,44 @@ fn globalVarDecl(...@@ -4513,29 +4474,44 @@ fn globalVarDecl(
4513 } else {4474 } else {
4514 return astgen.failNode(node, "unable to infer variable type", .{});4475 return astgen.failNode(node, "unable to infer variable type", .{});
4515 };4476 };
4477
4516 // We do this at the end so that the instruction index marks the end4478 // We do this at the end so that the instruction index marks the end
4517 // range of a top level declaration.4479 // range of a top level declaration.
4518 _ = try block_scope.addBreakWithSrcNode(.break_inline, block_inst, var_inst, node);4480 _ = try block_scope.addBreakWithSrcNode(.break_inline, decl_inst, var_inst, node);
4519 try block_scope.setBlockBody(block_inst);
45204481
4521 {4482 var align_gz = block_scope.makeSubBlock(scope);
4522 const contents_hash align(@alignOf(u32)) = std.zig.hashSrc(tree.getNodeSource(node));4483 if (var_decl.ast.align_node != 0) {
4523 wip_members.appendToDeclSlice(std.mem.bytesAsSlice(u32, &contents_hash));4484 const align_inst = try expr(&align_gz, &align_gz.base, coerced_align_ri, var_decl.ast.align_node);
4485 _ = try align_gz.addBreakWithSrcNode(.break_inline, decl_inst, align_inst, node);
4524 }4486 }
4525 {4487
4526 const line_delta = block_scope.decl_line - gz.decl_line;4488 var linksection_gz = align_gz.makeSubBlock(scope);
4527 wip_members.appendToDecl(line_delta);4489 if (var_decl.ast.section_node != 0) {
4528 }4490 const linksection_inst = try expr(&linksection_gz, &linksection_gz.base, coerced_linksection_ri, var_decl.ast.section_node);
4529 wip_members.appendToDecl(@intFromEnum(name_str_index));4491 _ = try linksection_gz.addBreakWithSrcNode(.break_inline, decl_inst, linksection_inst, node);
4530 wip_members.appendToDecl(@intFromEnum(block_inst));
4531 wip_members.appendToDecl(@intFromEnum(doc_comment_index)); // doc_comment wip
4532 if (align_inst != .none) {
4533 wip_members.appendToDecl(@intFromEnum(align_inst));
4534 }
4535 if (has_section_or_addrspace) {
4536 wip_members.appendToDecl(@intFromEnum(section_inst));
4537 wip_members.appendToDecl(@intFromEnum(addrspace_inst));
4538 }4492 }
4493
4494 var addrspace_gz = linksection_gz.makeSubBlock(scope);
4495 if (var_decl.ast.addrspace_node != 0) {
4496 const addrspace_inst = try expr(&addrspace_gz, &addrspace_gz.base, coerced_addrspace_ri, var_decl.ast.addrspace_node);
4497 _ = try addrspace_gz.addBreakWithSrcNode(.break_inline, decl_inst, addrspace_inst, node);
4498 }
4499
4500 try setDeclaration(
4501 decl_inst,
4502 std.zig.hashSrc(tree.getNodeSource(node)),
4503 .{ .named = name_token },
4504 block_scope.decl_line - gz.decl_line,
4505 is_pub,
4506 is_export,
4507 doc_comment_index,
4508 &block_scope,
4509 .{
4510 .align_gz = &align_gz,
4511 .linksection_gz = &linksection_gz,
4512 .addrspace_gz = &addrspace_gz,
4513 },
4514 );
4539}4515}
45404516
4541fn comptimeDecl(4517fn comptimeDecl(
...@@ -4551,8 +4527,8 @@ fn comptimeDecl(...@@ -4551,8 +4527,8 @@ fn comptimeDecl(
45514527
4552 // Up top so the ZIR instruction index marks the start range of this4528 // Up top so the ZIR instruction index marks the start range of this
4553 // top-level declaration.4529 // top-level declaration.
4554 const block_inst = try gz.makeBlockInst(.block_inline, node);4530 const decl_inst = try gz.makeBlockInst(.declaration, node);
4555 wip_members.nextDecl(false, false, false, false);4531 wip_members.nextDecl(decl_inst);
4556 astgen.advanceSourceCursorToNode(node);4532 astgen.advanceSourceCursorToNode(node);
45574533
4558 var decl_block: GenZir = .{4534 var decl_block: GenZir = .{
...@@ -4568,21 +4544,20 @@ fn comptimeDecl(...@@ -4568,21 +4544,20 @@ fn comptimeDecl(
45684544
4569 const block_result = try expr(&decl_block, &decl_block.base, .{ .rl = .none }, body_node);4545 const block_result = try expr(&decl_block, &decl_block.base, .{ .rl = .none }, body_node);
4570 if (decl_block.isEmpty() or !decl_block.refIsNoReturn(block_result)) {4546 if (decl_block.isEmpty() or !decl_block.refIsNoReturn(block_result)) {
4571 _ = try decl_block.addBreak(.break_inline, block_inst, .void_value);4547 _ = try decl_block.addBreak(.break_inline, decl_inst, .void_value);
4572 }4548 }
4573 try decl_block.setBlockBody(block_inst);
45744549
4575 {4550 try setDeclaration(
4576 const contents_hash align(@alignOf(u32)) = std.zig.hashSrc(tree.getNodeSource(node));4551 decl_inst,
4577 wip_members.appendToDeclSlice(std.mem.bytesAsSlice(u32, &contents_hash));4552 std.zig.hashSrc(tree.getNodeSource(node)),
4578 }4553 .@"comptime",
4579 {4554 decl_block.decl_line - gz.decl_line,
4580 const line_delta = decl_block.decl_line - gz.decl_line;4555 false,
4581 wip_members.appendToDecl(line_delta);4556 false,
4582 }4557 .empty,
4583 wip_members.appendToDecl(0);4558 &decl_block,
4584 wip_members.appendToDecl(@intFromEnum(block_inst));4559 null,
4585 wip_members.appendToDecl(0); // no doc comments on comptime decls4560 );
4586}4561}
45874562
4588fn usingnamespaceDecl(4563fn usingnamespaceDecl(
...@@ -4604,8 +4579,8 @@ fn usingnamespaceDecl(...@@ -4604,8 +4579,8 @@ fn usingnamespaceDecl(
4604 };4579 };
4605 // Up top so the ZIR instruction index marks the start range of this4580 // Up top so the ZIR instruction index marks the start range of this
4606 // top-level declaration.4581 // top-level declaration.
4607 const block_inst = try gz.makeBlockInst(.block_inline, node);4582 const decl_inst = try gz.makeBlockInst(.declaration, node);
4608 wip_members.nextDecl(is_pub, true, false, false);4583 wip_members.nextDecl(decl_inst);
4609 astgen.advanceSourceCursorToNode(node);4584 astgen.advanceSourceCursorToNode(node);
46104585
4611 var decl_block: GenZir = .{4586 var decl_block: GenZir = .{
...@@ -4620,20 +4595,19 @@ fn usingnamespaceDecl(...@@ -4620,20 +4595,19 @@ fn usingnamespaceDecl(
4620 defer decl_block.unstack();4595 defer decl_block.unstack();
46214596
4622 const namespace_inst = try typeExpr(&decl_block, &decl_block.base, type_expr);4597 const namespace_inst = try typeExpr(&decl_block, &decl_block.base, type_expr);
4623 _ = try decl_block.addBreak(.break_inline, block_inst, namespace_inst);4598 _ = try decl_block.addBreak(.break_inline, decl_inst, namespace_inst);
4624 try decl_block.setBlockBody(block_inst);4599
46254600 try setDeclaration(
4626 {4601 decl_inst,
4627 const contents_hash align(@alignOf(u32)) = std.zig.hashSrc(tree.getNodeSource(node));4602 std.zig.hashSrc(tree.getNodeSource(node)),
4628 wip_members.appendToDeclSlice(std.mem.bytesAsSlice(u32, &contents_hash));4603 .@"usingnamespace",
4629 }4604 decl_block.decl_line - gz.decl_line,
4630 {4605 is_pub,
4631 const line_delta = decl_block.decl_line - gz.decl_line;4606 false,
4632 wip_members.appendToDecl(line_delta);4607 .empty,
4633 }4608 &decl_block,
4634 wip_members.appendToDecl(0);4609 null,
4635 wip_members.appendToDecl(@intFromEnum(block_inst));4610 );
4636 wip_members.appendToDecl(0); // no doc comments on usingnamespace decls
4637}4611}
46384612
4639fn testDecl(4613fn testDecl(
...@@ -4649,9 +4623,9 @@ fn testDecl(...@@ -4649,9 +4623,9 @@ fn testDecl(
46494623
4650 // Up top so the ZIR instruction index marks the start range of this4624 // Up top so the ZIR instruction index marks the start range of this
4651 // top-level declaration.4625 // top-level declaration.
4652 const block_inst = try gz.makeBlockInst(.block_inline, node);4626 const decl_inst = try gz.makeBlockInst(.declaration, node);
46534627
4654 wip_members.nextDecl(false, false, false, false);4628 wip_members.nextDecl(decl_inst);
4655 astgen.advanceSourceCursorToNode(node);4629 astgen.advanceSourceCursorToNode(node);
46564630
4657 var decl_block: GenZir = .{4631 var decl_block: GenZir = .{
...@@ -4669,12 +4643,10 @@ fn testDecl(...@@ -4669,12 +4643,10 @@ fn testDecl(
4669 const token_tags = tree.tokens.items(.tag);4643 const token_tags = tree.tokens.items(.tag);
4670 const test_token = main_tokens[node];4644 const test_token = main_tokens[node];
4671 const test_name_token = test_token + 1;4645 const test_name_token = test_token + 1;
4672 const test_name_token_tag = token_tags[test_name_token];4646 const test_name: DeclarationName = switch (token_tags[test_name_token]) {
4673 const is_decltest = test_name_token_tag == .identifier;4647 else => .unnamed_test,
4674 const test_name: Zir.NullTerminatedString = blk: {4648 .string_literal => .{ .named_test = test_name_token },
4675 if (test_name_token_tag == .string_literal) {4649 .identifier => blk: {
4676 break :blk try astgen.testNameString(test_name_token);
4677 } else if (test_name_token_tag == .identifier) {
4678 const ident_name_raw = tree.tokenSlice(test_name_token);4650 const ident_name_raw = tree.tokenSlice(test_name_token);
46794651
4680 if (mem.eql(u8, ident_name_raw, "_")) return astgen.failTok(test_name_token, "'_' used as an identifier without @\"_\" syntax", .{});4652 if (mem.eql(u8, ident_name_raw, "_")) return astgen.failTok(test_name_token, "'_' used as an identifier without @\"_\" syntax", .{});
...@@ -4744,10 +4716,8 @@ fn testDecl(...@@ -4744,10 +4716,8 @@ fn testDecl(
4744 return astgen.failTok(test_name_token, "use of undeclared identifier '{s}'", .{ident_name});4716 return astgen.failTok(test_name_token, "use of undeclared identifier '{s}'", .{ident_name});
4745 }4717 }
47464718
4747 break :blk name_str_index;4719 break :blk .{ .decltest = name_str_index };
4748 }4720 },
4749 // String table index 1 has a special meaning here of test decl with no name.
4750 break :blk .unnamed_test_decl;
4751 };4721 };
47524722
4753 var fn_block: GenZir = .{4723 var fn_block: GenZir = .{
...@@ -4795,7 +4765,7 @@ fn testDecl(...@@ -4795,7 +4765,7 @@ fn testDecl(
47954765
4796 .lbrace_line = lbrace_line,4766 .lbrace_line = lbrace_line,
4797 .lbrace_column = lbrace_column,4767 .lbrace_column = lbrace_column,
4798 .param_block = block_inst,4768 .param_block = decl_inst,
4799 .body_gz = &fn_block,4769 .body_gz = &fn_block,
4800 .lib_name = .empty,4770 .lib_name = .empty,
4801 .is_var_args = false,4771 .is_var_args = false,
...@@ -4806,26 +4776,19 @@ fn testDecl(...@@ -4806,26 +4776,19 @@ fn testDecl(
4806 .noalias_bits = 0,4776 .noalias_bits = 0,
4807 });4777 });
48084778
4809 _ = try decl_block.addBreak(.break_inline, block_inst, func_inst);4779 _ = try decl_block.addBreak(.break_inline, decl_inst, func_inst);
4810 try decl_block.setBlockBody(block_inst);4780
48114781 try setDeclaration(
4812 {4782 decl_inst,
4813 const contents_hash align(@alignOf(u32)) = std.zig.hashSrc(tree.getNodeSource(node));4783 std.zig.hashSrc(tree.getNodeSource(node)),
4814 wip_members.appendToDeclSlice(std.mem.bytesAsSlice(u32, &contents_hash));4784 test_name,
4815 }4785 decl_block.decl_line - gz.decl_line,
4816 {4786 false,
4817 const line_delta = decl_block.decl_line - gz.decl_line;4787 false,
4818 wip_members.appendToDecl(line_delta);4788 .empty,
4819 }4789 &decl_block,
4820 if (is_decltest)4790 null,
4821 wip_members.appendToDecl(2) // 2 here means that it is a decltest, look at doc comment for name4791 );
4822 else
4823 wip_members.appendToDecl(@intFromEnum(test_name));
4824 wip_members.appendToDecl(@intFromEnum(block_inst));
4825 if (is_decltest)
4826 wip_members.appendToDecl(@intFromEnum(test_name)) // the doc comment on a decltest represents it's name
4827 else
4828 wip_members.appendToDecl(0); // no doc comments on test decls
4829}4792}
48304793
4831fn structDeclInner(4794fn structDeclInner(
...@@ -13524,3 +13487,106 @@ fn lowerAstErrors(astgen: *AstGen) !void {...@@ -13524,3 +13487,106 @@ fn lowerAstErrors(astgen: *AstGen) !void {
13524 try tree.renderError(parse_err, msg.writer(gpa));13487 try tree.renderError(parse_err, msg.writer(gpa));
13525 try astgen.appendErrorTokNotesOff(parse_err.token, extra_offset, "{s}", .{msg.items}, notes.items);13488 try astgen.appendErrorTokNotesOff(parse_err.token, extra_offset, "{s}", .{msg.items}, notes.items);
13526}13489}
13490
13491const DeclarationName = union(enum) {
13492 named: Ast.TokenIndex,
13493 named_test: Ast.TokenIndex,
13494 unnamed_test,
13495 decltest: Zir.NullTerminatedString,
13496 @"comptime",
13497 @"usingnamespace",
13498};
13499
13500/// Sets all extra data for a `declaration` instruction.
13501/// Unstacks `value_gz`, `align_gz`, `linksection_gz`, and `addrspace_gz`.
13502fn setDeclaration(
13503 decl_inst: Zir.Inst.Index,
13504 src_hash: std.zig.SrcHash,
13505 name: DeclarationName,
13506 line_offset: u32,
13507 is_pub: bool,
13508 is_export: bool,
13509 doc_comment: Zir.NullTerminatedString,
13510 value_gz: *GenZir,
13511 /// May be `null` if all these blocks would be empty.
13512 /// If `null`, then `value_gz` must have nothing stacked on it.
13513 extra_gzs: ?struct {
13514 /// Must be stacked on `value_gz`.
13515 align_gz: *GenZir,
13516 /// Must be stacked on `align_gz`.
13517 linksection_gz: *GenZir,
13518 /// Must be stacked on `linksection_gz`, and have nothing stacked on it.
13519 addrspace_gz: *GenZir,
13520 },
13521) !void {
13522 const astgen = value_gz.astgen;
13523 const gpa = astgen.gpa;
13524
13525 const empty_body: []Zir.Inst.Index = &.{};
13526 const value_body, const align_body, const linksection_body, const addrspace_body = if (extra_gzs) |e| .{
13527 value_gz.instructionsSliceUpto(e.align_gz),
13528 e.align_gz.instructionsSliceUpto(e.linksection_gz),
13529 e.linksection_gz.instructionsSliceUpto(e.addrspace_gz),
13530 e.addrspace_gz.instructionsSlice(),
13531 } else .{ value_gz.instructionsSlice(), empty_body, empty_body, empty_body };
13532
13533 const value_len = astgen.countBodyLenAfterFixups(value_body);
13534 const align_len = astgen.countBodyLenAfterFixups(align_body);
13535 const linksection_len = astgen.countBodyLenAfterFixups(linksection_body);
13536 const addrspace_len = astgen.countBodyLenAfterFixups(addrspace_body);
13537
13538 const true_doc_comment: Zir.NullTerminatedString = switch (name) {
13539 .decltest => |test_name| test_name,
13540 else => doc_comment,
13541 };
13542
13543 const src_hash_arr: [4]u32 = @bitCast(src_hash);
13544
13545 const extra: Zir.Inst.Declaration = .{
13546 .src_hash_0 = src_hash_arr[0],
13547 .src_hash_1 = src_hash_arr[1],
13548 .src_hash_2 = src_hash_arr[2],
13549 .src_hash_3 = src_hash_arr[3],
13550 .name = switch (name) {
13551 .named => |tok| @enumFromInt(@intFromEnum(try astgen.identAsString(tok))),
13552 .named_test => |tok| @enumFromInt(@intFromEnum(try astgen.testNameString(tok))),
13553 .unnamed_test => .unnamed_test,
13554 .decltest => .decltest,
13555 .@"comptime" => .@"comptime",
13556 .@"usingnamespace" => .@"usingnamespace",
13557 },
13558 .line_offset = line_offset,
13559 .flags = .{
13560 .value_body_len = @intCast(value_len),
13561 .is_pub = is_pub,
13562 .is_export = is_export,
13563 .has_doc_comment = true_doc_comment != .empty,
13564 .has_align_linksection_addrspace = align_len != 0 or linksection_len != 0 or addrspace_len != 0,
13565 },
13566 };
13567 astgen.instructions.items(.data)[@intFromEnum(decl_inst)].pl_node.payload_index = try astgen.addExtra(extra);
13568 if (extra.flags.has_doc_comment) {
13569 try astgen.extra.append(gpa, @intFromEnum(true_doc_comment));
13570 }
13571 if (extra.flags.has_align_linksection_addrspace) {
13572 try astgen.extra.appendSlice(gpa, &.{
13573 align_len,
13574 linksection_len,
13575 addrspace_len,
13576 });
13577 }
13578 try astgen.extra.ensureUnusedCapacity(gpa, value_len + align_len + linksection_len + addrspace_len);
13579 astgen.appendBodyWithFixups(value_body);
13580 if (extra.flags.has_align_linksection_addrspace) {
13581 astgen.appendBodyWithFixups(align_body);
13582 astgen.appendBodyWithFixups(linksection_body);
13583 astgen.appendBodyWithFixups(addrspace_body);
13584 }
13585
13586 if (extra_gzs) |e| {
13587 e.addrspace_gz.unstack();
13588 e.linksection_gz.unstack();
13589 e.align_gz.unstack();
13590 }
13591 value_gz.unstack();
13592}
src/Autodoc.zig+119-183
...@@ -2846,22 +2846,14 @@ fn walkInstruction(...@@ -2846,22 +2846,14 @@ fn walkInstruction(
2846 return res;2846 return res;
2847 },2847 },
2848 .block_inline => {2848 .block_inline => {
2849 return self.walkRef(2849 const pl_node = data[@intFromEnum(inst)].pl_node;
2850 const extra = file.zir.extraData(Zir.Inst.Block, pl_node.payload_index);
2851 return self.walkInlineBody(
2850 file,2852 file,
2851 parent_scope,2853 parent_scope,
2854 try self.srcLocInfo(file, pl_node.src_node, parent_src),
2852 parent_src,2855 parent_src,
2853 getBlockInlineBreak(file.zir, inst) orelse {2856 file.zir.bodySlice(extra.end, extra.data.body_len),
2854 const res = DocData.WalkResult{
2855 .typeRef = .{ .type = @intFromEnum(Ref.type_type) },
2856 .expr = .{ .comptimeExpr = self.comptime_exprs.items.len },
2857 };
2858 const pl_node = data[@intFromEnum(inst)].pl_node;
2859 const block_inline_expr = try self.getBlockSource(file, parent_src, pl_node.src_node);
2860 try self.comptime_exprs.append(self.arena, .{
2861 .code = block_inline_expr,
2862 });
2863 return res;
2864 },
2865 need_type,2857 need_type,
2866 call_ctx,2858 call_ctx,
2867 );2859 );
...@@ -4084,19 +4076,11 @@ fn analyzeAllDecls(...@@ -4084,19 +4076,11 @@ fn analyzeAllDecls(
4084 // First loop to discover decl names4076 // First loop to discover decl names
4085 {4077 {
4086 var it = original_it;4078 var it = original_it;
4087 while (it.next()) |d| {4079 while (it.next()) |zir_index| {
4088 const decl_name_index: Zir.NullTerminatedString = @enumFromInt(file.zir.extra[@intFromEnum(d.sub_index) + 5]);4080 const declaration, _ = file.zir.getDeclaration(zir_index);
4089 switch (decl_name_index) {4081 if (declaration.name.isNamedTest(file.zir)) continue;
4090 .empty,4082 const decl_name = declaration.name.toString(file.zir) orelse continue;
4091 .unnamed_test_decl,4083 try scope.insertDeclRef(self.arena, decl_name, .Pending);
4092 .decltest,
4093 => continue,
4094 _ => if (file.zir.nullTerminatedString(decl_name_index).len == 0) {
4095 continue;
4096 },
4097 }
4098
4099 try scope.insertDeclRef(self.arena, decl_name_index, .Pending);
4100 }4084 }
4101 }4085 }
41024086
...@@ -4104,147 +4088,114 @@ fn analyzeAllDecls(...@@ -4104,147 +4088,114 @@ fn analyzeAllDecls(
4104 {4088 {
4105 var it = original_it;4089 var it = original_it;
4106 var decl_indexes_slot = first_decl_indexes_slot;4090 var decl_indexes_slot = first_decl_indexes_slot;
4107 while (it.next()) |d| : (decl_indexes_slot += 1) {4091 while (it.next()) |zir_index| : (decl_indexes_slot += 1) {
4108 const decl_name_index = file.zir.extra[@intFromEnum(d.sub_index) + 5];4092 const pl_node = file.zir.instructions.items(.data)[@intFromEnum(zir_index)].pl_node;
4109 switch (decl_name_index) {4093 const extra = file.zir.extraData(Zir.Inst.Declaration, pl_node.payload_index);
4110 0 => {4094 if (extra.data.name != .@"usingnamespace") continue;
4111 const is_exported = @as(u1, @truncate(d.flags >> 1));4095 try self.analyzeUsingnamespaceDecl(
4112 switch (is_exported) {4096 file,
4113 0 => continue, // comptime decl4097 scope,
4114 1 => {4098 try self.srcLocInfo(file, pl_node.src_node, parent_src),
4115 try self.analyzeUsingnamespaceDecl(4099 decl_indexes,
4116 file,4100 priv_decl_indexes,
4117 scope,4101 extra.data,
4118 parent_src,4102 @intCast(extra.end),
4119 decl_indexes,4103 call_ctx,
4120 priv_decl_indexes,4104 );
4121 d,
4122 call_ctx,
4123 );
4124 },
4125 }
4126 },
4127 else => continue,
4128 }
4129 }4105 }
4130 }4106 }
41314107
4132 // Third loop to analyze all remaining decls4108 // Third loop to analyze all remaining decls
4133 var it = original_it;4109 {
4134 while (it.next()) |d| {4110 var it = original_it;
4135 const decl_name_index = file.zir.extra[@intFromEnum(d.sub_index) + 5];4111 while (it.next()) |zir_index| {
4136 switch (decl_name_index) {4112 const pl_node = file.zir.instructions.items(.data)[@intFromEnum(zir_index)].pl_node;
4137 0, 1 => continue, // skip over usingnamespace decls4113 const extra = file.zir.extraData(Zir.Inst.Declaration, pl_node.payload_index);
4138 2 => continue, // skip decltests4114 switch (extra.data.name) {
41394115 .@"comptime", .@"usingnamespace", .unnamed_test, .decltest => continue,
4140 else => if (file.zir.string_bytes[decl_name_index] == 0) {4116 _ => if (extra.data.name.isNamedTest(file.zir)) continue,
4141 continue;4117 }
4142 },4118 try self.analyzeDecl(
4119 file,
4120 scope,
4121 try self.srcLocInfo(file, pl_node.src_node, parent_src),
4122 decl_indexes,
4123 priv_decl_indexes,
4124 zir_index,
4125 extra.data,
4126 @intCast(extra.end),
4127 call_ctx,
4128 );
4143 }4129 }
4144
4145 try self.analyzeDecl(
4146 file,
4147 scope,
4148 parent_src,
4149 decl_indexes,
4150 priv_decl_indexes,
4151 d,
4152 call_ctx,
4153 );
4154 }4130 }
41554131
4156 // Fourth loop to analyze decltests4132 // Fourth loop to analyze decltests
4157 it = original_it;4133 var it = original_it;
4158 while (it.next()) |d| {4134 while (it.next()) |zir_index| {
4159 const decl_name_index = file.zir.extra[@intFromEnum(d.sub_index) + 5];4135 const pl_node = file.zir.instructions.items(.data)[@intFromEnum(zir_index)].pl_node;
4160 switch (decl_name_index) {4136 const extra = file.zir.extraData(Zir.Inst.Declaration, pl_node.payload_index);
4161 0, 1 => continue, // skip over usingnamespace decls4137 if (extra.data.name != .decltest) continue;
4162 2 => {},
4163 else => continue, // skip tests and normal decls
4164 }
4165
4166 try self.analyzeDecltest(4138 try self.analyzeDecltest(
4167 file,4139 file,
4168 scope,4140 scope,
4169 parent_src,4141 try self.srcLocInfo(file, pl_node.src_node, parent_src),
4170 d,4142 extra.data,
4143 @intCast(extra.end),
4171 );4144 );
4172 }4145 }
41734146
4174 return it.extra_index;4147 return it.extra_index;
4175}4148}
41764149
4150fn walkInlineBody(
4151 autodoc: *Autodoc,
4152 file: *File,
4153 scope: *Scope,
4154 block_src: SrcLocInfo,
4155 parent_src: SrcLocInfo,
4156 body: []const Zir.Inst.Index,
4157 need_type: bool,
4158 call_ctx: ?*const CallContext,
4159) AutodocErrors!DocData.WalkResult {
4160 const tags = file.zir.instructions.items(.tag);
4161 const break_inst = switch (tags[@intFromEnum(body[body.len - 1])]) {
4162 .condbr_inline => {
4163 // Unresolvable.
4164 const res: DocData.WalkResult = .{
4165 .typeRef = .{ .type = @intFromEnum(Ref.type_type) },
4166 .expr = .{ .comptimeExpr = autodoc.comptime_exprs.items.len },
4167 };
4168 const source = (try file.getTree(autodoc.zcu.gpa)).getNodeSource(block_src.src_node);
4169 try autodoc.comptime_exprs.append(autodoc.arena, .{
4170 .code = source,
4171 });
4172 return res;
4173 },
4174 .break_inline => body[body.len - 1],
4175 else => unreachable,
4176 };
4177 const break_data = file.zir.instructions.items(.data)[@intFromEnum(break_inst)].@"break";
4178 return autodoc.walkRef(file, scope, parent_src, break_data.operand, need_type, call_ctx);
4179}
4180
4177// Asserts the given decl is public4181// Asserts the given decl is public
4178fn analyzeDecl(4182fn analyzeDecl(
4179 self: *Autodoc,4183 self: *Autodoc,
4180 file: *File,4184 file: *File,
4181 scope: *Scope,4185 scope: *Scope,
4182 parent_src: SrcLocInfo,4186 decl_src: SrcLocInfo,
4183 decl_indexes: *std.ArrayListUnmanaged(usize),4187 decl_indexes: *std.ArrayListUnmanaged(usize),
4184 priv_decl_indexes: *std.ArrayListUnmanaged(usize),4188 priv_decl_indexes: *std.ArrayListUnmanaged(usize),
4185 d: Zir.DeclIterator.Item,4189 decl_inst: Zir.Inst.Index,
4190 declaration: Zir.Inst.Declaration,
4191 extra_index: u32,
4186 call_ctx: ?*const CallContext,4192 call_ctx: ?*const CallContext,
4187) AutodocErrors!void {4193) AutodocErrors!void {
4188 const data = file.zir.instructions.items(.data);4194 const bodies = declaration.getBodies(extra_index, file.zir);
4189 const is_pub = @as(u1, @truncate(d.flags >> 0)) != 0;4195 const name = file.zir.nullTerminatedString(declaration.name.toString(file.zir).?);
4190 // const is_exported = @truncate(u1, d.flags >> 1) != 0;
4191 const has_align = @as(u1, @truncate(d.flags >> 2)) != 0;
4192 const has_section_or_addrspace = @as(u1, @truncate(d.flags >> 3)) != 0;
4193
4194 var extra_index = @intFromEnum(d.sub_index);
4195 // const hash_u32s = file.zir.extra[extra_index..][0..4];
4196
4197 extra_index += 4;
4198 // const line = file.zir.extra[extra_index];
4199
4200 extra_index += 1;
4201 const decl_name_index: Zir.NullTerminatedString = @enumFromInt(file.zir.extra[extra_index]);
4202
4203 extra_index += 1;
4204 const value_index: Zir.Inst.Index = @enumFromInt(file.zir.extra[extra_index]);
4205
4206 extra_index += 1;
4207 const doc_comment_index: Zir.NullTerminatedString = @enumFromInt(file.zir.extra[extra_index]);
4208
4209 extra_index += 1;
4210 const align_inst: Zir.Inst.Ref = if (!has_align) .none else inst: {
4211 const inst: Zir.Inst.Ref = @enumFromInt(file.zir.extra[extra_index]);
4212 extra_index += 1;
4213 break :inst inst;
4214 };
4215 _ = align_inst;
4216
4217 const section_inst: Zir.Inst.Ref = if (!has_section_or_addrspace) .none else inst: {
4218 const inst: Zir.Inst.Ref = @enumFromInt(file.zir.extra[extra_index]);
4219 extra_index += 1;
4220 break :inst inst;
4221 };
4222 _ = section_inst;
42234196
4224 const addrspace_inst: Zir.Inst.Ref = if (!has_section_or_addrspace) .none else inst: {4197 const doc_comment: ?[]const u8 = if (declaration.flags.has_doc_comment)
4225 const inst: Zir.Inst.Ref = @enumFromInt(file.zir.extra[extra_index]);4198 file.zir.nullTerminatedString(@enumFromInt(file.zir.extra[extra_index]))
4226 extra_index += 1;
4227 break :inst inst;
4228 };
4229 _ = addrspace_inst;
4230
4231 // This is known to work because decl values are always block_inlines
4232 const value_pl_node = data[@intFromEnum(value_index)].pl_node;
4233 const decl_src = try self.srcLocInfo(file, value_pl_node.src_node, parent_src);
4234
4235 const name: []const u8 = switch (decl_name_index) {
4236 .empty, .unnamed_test_decl, .decltest => unreachable,
4237 _ => blk: {
4238 if (decl_name_index == .empty) {
4239 // test decl
4240 unreachable;
4241 }
4242 break :blk file.zir.nullTerminatedString(decl_name_index);
4243 },
4244 };
4245
4246 const doc_comment: ?[]const u8 = if (doc_comment_index != .empty)
4247 file.zir.nullTerminatedString(doc_comment_index)
4248 else4199 else
4249 null;4200 null;
42504201
...@@ -4261,16 +4212,22 @@ fn analyzeDecl(...@@ -4261,16 +4212,22 @@ fn analyzeDecl(
4261 break :idx idx;4212 break :idx idx;
4262 };4213 };
42634214
4264 const walk_result = try self.walkInstruction(4215 const walk_result = try self.walkInlineBody(
4265 file,4216 file,
4266 scope,4217 scope,
4267 decl_src,4218 decl_src,
4268 value_index,4219 decl_src,
4220 bodies.value_body,
4269 true,4221 true,
4270 call_ctx,4222 call_ctx,
4271 );4223 );
42724224
4273 const kind: []const u8 = if (try self.declIsVar(file, value_pl_node.src_node, parent_src)) "var" else "const";4225 const tree = try file.getTree(self.zcu.gpa);
4226 const kind_token = tree.nodes.items(.main_token)[decl_src.src_node];
4227 const kind: []const u8 = switch (tree.tokens.items(.tag)[kind_token]) {
4228 .keyword_var => "var",
4229 else => "const",
4230 };
42744231
4275 const decls_slot_index = self.decls.items.len;4232 const decls_slot_index = self.decls.items.len;
4276 try self.decls.append(self.arena, .{4233 try self.decls.append(self.arena, .{
...@@ -4281,13 +4238,13 @@ fn analyzeDecl(...@@ -4281,13 +4238,13 @@ fn analyzeDecl(
4281 .parent_container = scope.enclosing_type,4238 .parent_container = scope.enclosing_type,
4282 });4239 });
42834240
4284 if (is_pub) {4241 if (declaration.flags.is_pub) {
4285 try decl_indexes.append(self.arena, decls_slot_index);4242 try decl_indexes.append(self.arena, decls_slot_index);
4286 } else {4243 } else {
4287 try priv_decl_indexes.append(self.arena, decls_slot_index);4244 try priv_decl_indexes.append(self.arena, decls_slot_index);
4288 }4245 }
42894246
4290 const decl_status_ptr = scope.resolveDeclName(decl_name_index, file, .none);4247 const decl_status_ptr = scope.resolveDeclName(declaration.name.toString(file.zir).?, file, .none);
4291 std.debug.assert(decl_status_ptr.* == .Pending);4248 std.debug.assert(decl_status_ptr.* == .Pending);
4292 decl_status_ptr.* = .{ .Analyzed = decls_slot_index };4249 decl_status_ptr.* = .{ .Analyzed = decls_slot_index };
42934250
...@@ -4296,7 +4253,7 @@ fn analyzeDecl(...@@ -4296,7 +4253,7 @@ fn analyzeDecl(
4296 for (paths.items) |resume_info| {4253 for (paths.items) |resume_info| {
4297 try self.tryResolveRefPath(4254 try self.tryResolveRefPath(
4298 resume_info.file,4255 resume_info.file,
4299 value_index,4256 decl_inst,
4300 resume_info.ref_path,4257 resume_info.ref_path,
4301 );4258 );
4302 }4259 }
...@@ -4312,24 +4269,17 @@ fn analyzeUsingnamespaceDecl(...@@ -4312,24 +4269,17 @@ fn analyzeUsingnamespaceDecl(
4312 self: *Autodoc,4269 self: *Autodoc,
4313 file: *File,4270 file: *File,
4314 scope: *Scope,4271 scope: *Scope,
4315 parent_src: SrcLocInfo,4272 decl_src: SrcLocInfo,
4316 decl_indexes: *std.ArrayListUnmanaged(usize),4273 decl_indexes: *std.ArrayListUnmanaged(usize),
4317 priv_decl_indexes: *std.ArrayListUnmanaged(usize),4274 priv_decl_indexes: *std.ArrayListUnmanaged(usize),
4318 d: Zir.DeclIterator.Item,4275 declaration: Zir.Inst.Declaration,
4276 extra_index: u32,
4319 call_ctx: ?*const CallContext,4277 call_ctx: ?*const CallContext,
4320) AutodocErrors!void {4278) AutodocErrors!void {
4321 const data = file.zir.instructions.items(.data);4279 const bodies = declaration.getBodies(extra_index, file.zir);
43224280
4323 const is_pub = @as(u1, @truncate(d.flags)) != 0;4281 const doc_comment: ?[]const u8 = if (declaration.flags.has_doc_comment)
4324 const value_index: Zir.Inst.Index = @enumFromInt(file.zir.extra[@intFromEnum(d.sub_index) + 6]);4282 file.zir.nullTerminatedString(@enumFromInt(file.zir.extra[extra_index]))
4325 const doc_comment_index: Zir.NullTerminatedString = @enumFromInt(file.zir.extra[@intFromEnum(d.sub_index) + 7]);
4326
4327 // This is known to work because decl values are always block_inlines
4328 const value_pl_node = data[@intFromEnum(value_index)].pl_node;
4329 const decl_src = try self.srcLocInfo(file, value_pl_node.src_node, parent_src);
4330
4331 const doc_comment: ?[]const u8 = if (doc_comment_index != .empty)
4332 file.zir.nullTerminatedString(doc_comment_index)
4333 else4283 else
4334 null;4284 null;
43354285
...@@ -4346,11 +4296,12 @@ fn analyzeUsingnamespaceDecl(...@@ -4346,11 +4296,12 @@ fn analyzeUsingnamespaceDecl(
4346 break :idx idx;4296 break :idx idx;
4347 };4297 };
43484298
4349 const walk_result = try self.walkInstruction(4299 const walk_result = try self.walkInlineBody(
4350 file,4300 file,
4351 scope,4301 scope,
4352 decl_src,4302 decl_src,
4353 value_index,4303 decl_src,
4304 bodies.value_body,
4354 true,4305 true,
4355 call_ctx,4306 call_ctx,
4356 );4307 );
...@@ -4365,7 +4316,7 @@ fn analyzeUsingnamespaceDecl(...@@ -4365,7 +4316,7 @@ fn analyzeUsingnamespaceDecl(
4365 .parent_container = scope.enclosing_type,4316 .parent_container = scope.enclosing_type,
4366 });4317 });
43674318
4368 if (is_pub) {4319 if (declaration.flags.is_pub) {
4369 try decl_indexes.append(self.arena, decl_slot_index);4320 try decl_indexes.append(self.arena, decl_slot_index);
4370 } else {4321 } else {
4371 try priv_decl_indexes.append(self.arena, decl_slot_index);4322 try priv_decl_indexes.append(self.arena, decl_slot_index);
...@@ -4376,18 +4327,14 @@ fn analyzeDecltest(...@@ -4376,18 +4327,14 @@ fn analyzeDecltest(
4376 self: *Autodoc,4327 self: *Autodoc,
4377 file: *File,4328 file: *File,
4378 scope: *Scope,4329 scope: *Scope,
4379 parent_src: SrcLocInfo,4330 decl_src: SrcLocInfo,
4380 d: Zir.DeclIterator.Item,4331 declaration: Zir.Inst.Declaration,
4332 extra_index: u32,
4381) AutodocErrors!void {4333) AutodocErrors!void {
4382 const data = file.zir.instructions.items(.data);4334 std.debug.assert(declaration.flags.has_doc_comment);
43834335 const decl_name_index: Zir.NullTerminatedString = @enumFromInt(file.zir.extra[extra_index]);
4384 const value_index = file.zir.extra[@intFromEnum(d.sub_index) + 6];
4385 const decl_name_index: Zir.NullTerminatedString = @enumFromInt(file.zir.extra[@intFromEnum(d.sub_index) + 7]);
4386
4387 const value_pl_node = data[value_index].pl_node;
4388 const decl_src = try self.srcLocInfo(file, value_pl_node.src_node, parent_src);
43894336
4390 const test_source_code = try self.getBlockSource(file, parent_src, value_pl_node.src_node);4337 const test_source_code = (try file.getTree(self.zcu.gpa)).getNodeSource(decl_src.src_node);
43914338
4392 const decl_name: ?[]const u8 = if (decl_name_index != .empty)4339 const decl_name: ?[]const u8 = if (decl_name_index != .empty)
4393 file.zir.nullTerminatedString(decl_name_index)4340 file.zir.nullTerminatedString(decl_name_index)
...@@ -5830,17 +5777,6 @@ fn walkRef(...@@ -5830,17 +5777,6 @@ fn walkRef(
5830 }5777 }
5831}5778}
58325779
5833fn getBlockInlineBreak(zir: Zir, inst: Zir.Inst.Index) ?Zir.Inst.Ref {
5834 const tags = zir.instructions.items(.tag);
5835 const data = zir.instructions.items(.data);
5836 const pl_node = data[@intFromEnum(inst)].pl_node;
5837 const extra = zir.extraData(Zir.Inst.Block, pl_node.payload_index);
5838 const break_index = zir.extra[extra.end..][extra.data.body_len - 1];
5839 if (tags[break_index] == .condbr_inline) return null;
5840 std.debug.assert(tags[break_index] == .break_inline);
5841 return data[break_index].@"break".operand;
5842}
5843
5844fn printWithContext(5780fn printWithContext(
5845 file: *File,5781 file: *File,
5846 inst: Zir.Inst.Index,5782 inst: Zir.Inst.Index,
src/Compilation.zig+4-1
...@@ -2802,6 +2802,7 @@ const Header = extern struct {...@@ -2802,6 +2802,7 @@ const Header = extern struct {
2802 extra_len: u32,2802 extra_len: u32,
2803 limbs_len: u32,2803 limbs_len: u32,
2804 string_bytes_len: u32,2804 string_bytes_len: u32,
2805 tracked_insts_len: u32,
2805 },2806 },
2806};2807};
28072808
...@@ -2809,7 +2810,7 @@ const Header = extern struct {...@@ -2809,7 +2810,7 @@ const Header = extern struct {
2809/// saved, such as the target and most CLI flags. A cache hit will only occur2810/// saved, such as the target and most CLI flags. A cache hit will only occur
2810/// when subsequent compiler invocations use the same set of flags.2811/// when subsequent compiler invocations use the same set of flags.
2811pub fn saveState(comp: *Compilation) !void {2812pub fn saveState(comp: *Compilation) !void {
2812 var bufs_list: [6]std.os.iovec_const = undefined;2813 var bufs_list: [7]std.os.iovec_const = undefined;
2813 var bufs_len: usize = 0;2814 var bufs_len: usize = 0;
28142815
2815 const lf = comp.bin_file orelse return;2816 const lf = comp.bin_file orelse return;
...@@ -2822,6 +2823,7 @@ pub fn saveState(comp: *Compilation) !void {...@@ -2822,6 +2823,7 @@ pub fn saveState(comp: *Compilation) !void {
2822 .extra_len = @intCast(ip.extra.items.len),2823 .extra_len = @intCast(ip.extra.items.len),
2823 .limbs_len = @intCast(ip.limbs.items.len),2824 .limbs_len = @intCast(ip.limbs.items.len),
2824 .string_bytes_len = @intCast(ip.string_bytes.items.len),2825 .string_bytes_len = @intCast(ip.string_bytes.items.len),
2826 .tracked_insts_len = @intCast(ip.tracked_insts.count()),
2825 },2827 },
2826 };2828 };
2827 addBuf(&bufs_list, &bufs_len, mem.asBytes(&header));2829 addBuf(&bufs_list, &bufs_len, mem.asBytes(&header));
...@@ -2830,6 +2832,7 @@ pub fn saveState(comp: *Compilation) !void {...@@ -2830,6 +2832,7 @@ pub fn saveState(comp: *Compilation) !void {
2830 addBuf(&bufs_list, &bufs_len, mem.sliceAsBytes(ip.items.items(.data)));2832 addBuf(&bufs_list, &bufs_len, mem.sliceAsBytes(ip.items.items(.data)));
2831 addBuf(&bufs_list, &bufs_len, mem.sliceAsBytes(ip.items.items(.tag)));2833 addBuf(&bufs_list, &bufs_len, mem.sliceAsBytes(ip.items.items(.tag)));
2832 addBuf(&bufs_list, &bufs_len, ip.string_bytes.items);2834 addBuf(&bufs_list, &bufs_len, ip.string_bytes.items);
2835 addBuf(&bufs_list, &bufs_len, mem.sliceAsBytes(ip.tracked_insts.keys()));
28332836
2834 // TODO: compilation errors2837 // TODO: compilation errors
2835 // TODO: files2838 // TODO: files
src/InternPool.zig+51-21
...@@ -54,6 +54,34 @@ string_table: std.HashMapUnmanaged(...@@ -54,6 +54,34 @@ string_table: std.HashMapUnmanaged(
54 std.hash_map.default_max_load_percentage,54 std.hash_map.default_max_load_percentage,
55) = .{},55) = .{},
5656
57/// An index into `tracked_insts` gives a reference to a single ZIR instruction which
58/// persists across incremental updates.
59tracked_insts: std.AutoArrayHashMapUnmanaged(TrackedInst, void) = .{},
60
61pub const TrackedInst = extern struct {
62 path_digest: Cache.BinDigest,
63 inst: Zir.Inst.Index,
64 comptime {
65 // The fields should be tightly packed. See also serialiation logic in `Compilation.saveState`.
66 assert(@sizeOf(@This()) == Cache.bin_digest_len + @sizeOf(Zir.Inst.Index));
67 }
68 pub const Index = enum(u32) {
69 _,
70 pub fn resolve(i: TrackedInst.Index, ip: *const InternPool) Zir.Inst.Index {
71 return ip.tracked_insts.keys()[@intFromEnum(i)].inst;
72 }
73 };
74};
75
76pub fn trackZir(ip: *InternPool, gpa: Allocator, file: *Module.File, inst: Zir.Inst.Index) Allocator.Error!TrackedInst.Index {
77 const key: TrackedInst = .{
78 .path_digest = file.path_digest,
79 .inst = inst,
80 };
81 const gop = try ip.tracked_insts.getOrPut(gpa, key);
82 return @enumFromInt(gop.index);
83}
84
57const FieldMap = std.ArrayHashMapUnmanaged(void, void, std.array_hash_map.AutoContext(void), false);85const FieldMap = std.ArrayHashMapUnmanaged(void, void, std.array_hash_map.AutoContext(void), false);
5886
59const builtin = @import("builtin");87const builtin = @import("builtin");
...@@ -62,11 +90,13 @@ const Allocator = std.mem.Allocator;...@@ -62,11 +90,13 @@ const Allocator = std.mem.Allocator;
62const assert = std.debug.assert;90const assert = std.debug.assert;
63const BigIntConst = std.math.big.int.Const;91const BigIntConst = std.math.big.int.Const;
64const BigIntMutable = std.math.big.int.Mutable;92const BigIntMutable = std.math.big.int.Mutable;
93const Cache = std.Build.Cache;
65const Limb = std.math.big.Limb;94const Limb = std.math.big.Limb;
66const Hash = std.hash.Wyhash;95const Hash = std.hash.Wyhash;
6796
68const InternPool = @This();97const InternPool = @This();
69const Module = @import("Module.zig");98const Module = @import("Module.zig");
99const Zcu = Module;
70const Zir = @import("Zir.zig");100const Zir = @import("Zir.zig");
71101
72const KeyAdapter = struct {102const KeyAdapter = struct {
...@@ -409,7 +439,7 @@ pub const Key = union(enum) {...@@ -409,7 +439,7 @@ pub const Key = union(enum) {
409 /// `none` when the struct has no declarations.439 /// `none` when the struct has no declarations.
410 namespace: OptionalNamespaceIndex,440 namespace: OptionalNamespaceIndex,
411 /// Index of the struct_decl ZIR instruction.441 /// Index of the struct_decl ZIR instruction.
412 zir_index: Zir.Inst.Index,442 zir_index: TrackedInst.Index,
413 layout: std.builtin.Type.ContainerLayout,443 layout: std.builtin.Type.ContainerLayout,
414 field_names: NullTerminatedString.Slice,444 field_names: NullTerminatedString.Slice,
415 field_types: Index.Slice,445 field_types: Index.Slice,
...@@ -653,7 +683,7 @@ pub const Key = union(enum) {...@@ -653,7 +683,7 @@ pub const Key = union(enum) {
653 }683 }
654684
655 /// Asserts the struct is not packed.685 /// Asserts the struct is not packed.
656 pub fn setZirIndex(s: @This(), ip: *InternPool, new_zir_index: Zir.Inst.Index) void {686 pub fn setZirIndex(s: @This(), ip: *InternPool, new_zir_index: TrackedInst.Index) void {
657 assert(s.layout != .Packed);687 assert(s.layout != .Packed);
658 const field_index = std.meta.fieldIndex(Tag.TypeStruct, "zir_index").?;688 const field_index = std.meta.fieldIndex(Tag.TypeStruct, "zir_index").?;
659 ip.extra.items[s.extra_index + field_index] = @intFromEnum(new_zir_index);689 ip.extra.items[s.extra_index + field_index] = @intFromEnum(new_zir_index);
...@@ -769,7 +799,7 @@ pub const Key = union(enum) {...@@ -769,7 +799,7 @@ pub const Key = union(enum) {
769 flags: Tag.TypeUnion.Flags,799 flags: Tag.TypeUnion.Flags,
770 /// The enum that provides the list of field names and values.800 /// The enum that provides the list of field names and values.
771 enum_tag_ty: Index,801 enum_tag_ty: Index,
772 zir_index: Zir.Inst.Index,802 zir_index: TrackedInst.Index,
773803
774 /// The returned pointer expires with any addition to the `InternPool`.804 /// The returned pointer expires with any addition to the `InternPool`.
775 pub fn flagsPtr(self: @This(), ip: *const InternPool) *Tag.TypeUnion.Flags {805 pub fn flagsPtr(self: @This(), ip: *const InternPool) *Tag.TypeUnion.Flags {
...@@ -1056,7 +1086,7 @@ pub const Key = union(enum) {...@@ -1056,7 +1086,7 @@ pub const Key = union(enum) {
1056 /// the body. We store this rather than the body directly so that when ZIR1086 /// the body. We store this rather than the body directly so that when ZIR
1057 /// is regenerated on update(), we can map this to the new corresponding1087 /// is regenerated on update(), we can map this to the new corresponding
1058 /// ZIR instruction.1088 /// ZIR instruction.
1059 zir_body_inst: Zir.Inst.Index,1089 zir_body_inst: TrackedInst.Index,
1060 /// Relative to owner Decl.1090 /// Relative to owner Decl.
1061 lbrace_line: u32,1091 lbrace_line: u32,
1062 /// Relative to owner Decl.1092 /// Relative to owner Decl.
...@@ -1082,7 +1112,7 @@ pub const Key = union(enum) {...@@ -1082,7 +1112,7 @@ pub const Key = union(enum) {
1082 }1112 }
10831113
1084 /// Returns a pointer that becomes invalid after any additions to the `InternPool`.1114 /// Returns a pointer that becomes invalid after any additions to the `InternPool`.
1085 pub fn zirBodyInst(func: *const Func, ip: *const InternPool) *Zir.Inst.Index {1115 pub fn zirBodyInst(func: *const Func, ip: *const InternPool) *TrackedInst.Index {
1086 return @ptrCast(&ip.extra.items[func.zir_body_inst_extra_index]);1116 return @ptrCast(&ip.extra.items[func.zir_body_inst_extra_index]);
1087 }1117 }
10881118
...@@ -1860,7 +1890,7 @@ pub const UnionType = struct {...@@ -1860,7 +1890,7 @@ pub const UnionType = struct {
1860 /// If this slice has length 0 it means all elements are `none`.1890 /// If this slice has length 0 it means all elements are `none`.
1861 field_aligns: Alignment.Slice,1891 field_aligns: Alignment.Slice,
1862 /// Index of the union_decl ZIR instruction.1892 /// Index of the union_decl ZIR instruction.
1863 zir_index: Zir.Inst.Index,1893 zir_index: TrackedInst.Index,
1864 /// Index into extra array of the `flags` field.1894 /// Index into extra array of the `flags` field.
1865 flags_index: u32,1895 flags_index: u32,
1866 /// Copied from `enum_tag_ty`.1896 /// Copied from `enum_tag_ty`.
...@@ -1954,10 +1984,10 @@ pub const UnionType = struct {...@@ -1954,10 +1984,10 @@ pub const UnionType = struct {
1954 }1984 }
19551985
1956 /// This does not mutate the field of UnionType.1986 /// This does not mutate the field of UnionType.
1957 pub fn setZirIndex(self: @This(), ip: *InternPool, new_zir_index: Zir.Inst.Index) void {1987 pub fn setZirIndex(self: @This(), ip: *InternPool, new_zir_index: TrackedInst.Index) void {
1958 const flags_field_index = std.meta.fieldIndex(Tag.TypeUnion, "flags").?;1988 const flags_field_index = std.meta.fieldIndex(Tag.TypeUnion, "flags").?;
1959 const zir_index_field_index = std.meta.fieldIndex(Tag.TypeUnion, "zir_index").?;1989 const zir_index_field_index = std.meta.fieldIndex(Tag.TypeUnion, "zir_index").?;
1960 const ptr: *Zir.Inst.Index =1990 const ptr: *TrackedInst.Index =
1961 @ptrCast(&ip.extra.items[self.flags_index - flags_field_index + zir_index_field_index]);1991 @ptrCast(&ip.extra.items[self.flags_index - flags_field_index + zir_index_field_index]);
1962 ptr.* = new_zir_index;1992 ptr.* = new_zir_index;
1963 }1993 }
...@@ -2976,7 +3006,7 @@ pub const Tag = enum(u8) {...@@ -2976,7 +3006,7 @@ pub const Tag = enum(u8) {
2976 analysis: FuncAnalysis,3006 analysis: FuncAnalysis,
2977 owner_decl: DeclIndex,3007 owner_decl: DeclIndex,
2978 ty: Index,3008 ty: Index,
2979 zir_body_inst: Zir.Inst.Index,3009 zir_body_inst: TrackedInst.Index,
2980 lbrace_line: u32,3010 lbrace_line: u32,
2981 rbrace_line: u32,3011 rbrace_line: u32,
2982 lbrace_column: u32,3012 lbrace_column: u32,
...@@ -3050,7 +3080,7 @@ pub const Tag = enum(u8) {...@@ -3050,7 +3080,7 @@ pub const Tag = enum(u8) {
3050 namespace: NamespaceIndex,3080 namespace: NamespaceIndex,
3051 /// The enum that provides the list of field names and values.3081 /// The enum that provides the list of field names and values.
3052 tag_ty: Index,3082 tag_ty: Index,
3053 zir_index: Zir.Inst.Index,3083 zir_index: TrackedInst.Index,
30543084
3055 pub const Flags = packed struct(u32) {3085 pub const Flags = packed struct(u32) {
3056 runtime_tag: UnionType.RuntimeTag,3086 runtime_tag: UnionType.RuntimeTag,
...@@ -3072,7 +3102,7 @@ pub const Tag = enum(u8) {...@@ -3072,7 +3102,7 @@ pub const Tag = enum(u8) {
3072 /// 2. init: Index for each fields_len // if tag is type_struct_packed_inits3102 /// 2. init: Index for each fields_len // if tag is type_struct_packed_inits
3073 pub const TypeStructPacked = struct {3103 pub const TypeStructPacked = struct {
3074 decl: DeclIndex,3104 decl: DeclIndex,
3075 zir_index: Zir.Inst.Index,3105 zir_index: TrackedInst.Index,
3076 fields_len: u32,3106 fields_len: u32,
3077 namespace: OptionalNamespaceIndex,3107 namespace: OptionalNamespaceIndex,
3078 backing_int_ty: Index,3108 backing_int_ty: Index,
...@@ -3119,7 +3149,7 @@ pub const Tag = enum(u8) {...@@ -3119,7 +3149,7 @@ pub const Tag = enum(u8) {
3119 /// 7. field_offset: u32 // for each field in declared order, undef until layout_resolved3149 /// 7. field_offset: u32 // for each field in declared order, undef until layout_resolved
3120 pub const TypeStruct = struct {3150 pub const TypeStruct = struct {
3121 decl: DeclIndex,3151 decl: DeclIndex,
3122 zir_index: Zir.Inst.Index,3152 zir_index: TrackedInst.Index,
3123 fields_len: u32,3153 fields_len: u32,
3124 flags: Flags,3154 flags: Flags,
3125 size: u32,3155 size: u32,
...@@ -3708,6 +3738,8 @@ pub fn deinit(ip: *InternPool, gpa: Allocator) void {...@@ -3708,6 +3738,8 @@ pub fn deinit(ip: *InternPool, gpa: Allocator) void {
37083738
3709 ip.string_table.deinit(gpa);3739 ip.string_table.deinit(gpa);
37103740
3741 ip.tracked_insts.deinit(gpa);
3742
3711 ip.* = undefined;3743 ip.* = undefined;
3712}3744}
37133745
...@@ -5358,7 +5390,7 @@ pub const UnionTypeInit = struct {...@@ -5358,7 +5390,7 @@ pub const UnionTypeInit = struct {
5358 flags: Tag.TypeUnion.Flags,5390 flags: Tag.TypeUnion.Flags,
5359 decl: DeclIndex,5391 decl: DeclIndex,
5360 namespace: NamespaceIndex,5392 namespace: NamespaceIndex,
5361 zir_index: Zir.Inst.Index,5393 zir_index: TrackedInst.Index,
5362 fields_len: u32,5394 fields_len: u32,
5363 enum_tag_ty: Index,5395 enum_tag_ty: Index,
5364 /// May have length 0 which leaves the values unset until later.5396 /// May have length 0 which leaves the values unset until later.
...@@ -5430,7 +5462,7 @@ pub const StructTypeInit = struct {...@@ -5430,7 +5462,7 @@ pub const StructTypeInit = struct {
5430 decl: DeclIndex,5462 decl: DeclIndex,
5431 namespace: OptionalNamespaceIndex,5463 namespace: OptionalNamespaceIndex,
5432 layout: std.builtin.Type.ContainerLayout,5464 layout: std.builtin.Type.ContainerLayout,
5433 zir_index: Zir.Inst.Index,5465 zir_index: TrackedInst.Index,
5434 fields_len: u32,5466 fields_len: u32,
5435 known_non_opv: bool,5467 known_non_opv: bool,
5436 requires_comptime: RequiresComptime,5468 requires_comptime: RequiresComptime,
...@@ -5704,7 +5736,7 @@ pub fn getExternFunc(ip: *InternPool, gpa: Allocator, key: Key.ExternFunc) Alloc...@@ -5704,7 +5736,7 @@ pub fn getExternFunc(ip: *InternPool, gpa: Allocator, key: Key.ExternFunc) Alloc
5704pub const GetFuncDeclKey = struct {5736pub const GetFuncDeclKey = struct {
5705 owner_decl: DeclIndex,5737 owner_decl: DeclIndex,
5706 ty: Index,5738 ty: Index,
5707 zir_body_inst: Zir.Inst.Index,5739 zir_body_inst: TrackedInst.Index,
5708 lbrace_line: u32,5740 lbrace_line: u32,
5709 rbrace_line: u32,5741 rbrace_line: u32,
5710 lbrace_column: u32,5742 lbrace_column: u32,
...@@ -5773,7 +5805,7 @@ pub const GetFuncDeclIesKey = struct {...@@ -5773,7 +5805,7 @@ pub const GetFuncDeclIesKey = struct {
5773 is_var_args: bool,5805 is_var_args: bool,
5774 is_generic: bool,5806 is_generic: bool,
5775 is_noinline: bool,5807 is_noinline: bool,
5776 zir_body_inst: Zir.Inst.Index,5808 zir_body_inst: TrackedInst.Index,
5777 lbrace_line: u32,5809 lbrace_line: u32,
5778 rbrace_line: u32,5810 rbrace_line: u32,
5779 lbrace_column: u32,5811 lbrace_column: u32,
...@@ -6186,8 +6218,6 @@ fn finishFuncInstance(...@@ -6186,8 +6218,6 @@ fn finishFuncInstance(
6186 .generation = generation,6218 .generation = generation,
6187 .is_pub = fn_owner_decl.is_pub,6219 .is_pub = fn_owner_decl.is_pub,
6188 .is_exported = fn_owner_decl.is_exported,6220 .is_exported = fn_owner_decl.is_exported,
6189 .has_linksection_or_addrspace = fn_owner_decl.has_linksection_or_addrspace,
6190 .has_align = fn_owner_decl.has_align,
6191 .alive = true,6221 .alive = true,
6192 .kind = .anon,6222 .kind = .anon,
6193 });6223 });
...@@ -6537,7 +6567,7 @@ fn addExtraAssumeCapacity(ip: *InternPool, extra: anytype) u32 {...@@ -6537,7 +6567,7 @@ fn addExtraAssumeCapacity(ip: *InternPool, extra: anytype) u32 {
6537 NullTerminatedString,6567 NullTerminatedString,
6538 OptionalNullTerminatedString,6568 OptionalNullTerminatedString,
6539 Tag.TypePointer.VectorIndex,6569 Tag.TypePointer.VectorIndex,
6540 Zir.Inst.Index,6570 TrackedInst.Index,
6541 => @intFromEnum(@field(extra, field.name)),6571 => @intFromEnum(@field(extra, field.name)),
65426572
6543 u32,6573 u32,
...@@ -6613,7 +6643,7 @@ fn extraDataTrail(ip: *const InternPool, comptime T: type, index: usize) struct...@@ -6613,7 +6643,7 @@ fn extraDataTrail(ip: *const InternPool, comptime T: type, index: usize) struct
6613 NullTerminatedString,6643 NullTerminatedString,
6614 OptionalNullTerminatedString,6644 OptionalNullTerminatedString,
6615 Tag.TypePointer.VectorIndex,6645 Tag.TypePointer.VectorIndex,
6616 Zir.Inst.Index,6646 TrackedInst.Index,
6617 => @enumFromInt(int32),6647 => @enumFromInt(int32),
66186648
6619 u32,6649 u32,
...@@ -8319,7 +8349,7 @@ pub fn funcHasInferredErrorSet(ip: *const InternPool, i: Index) bool {...@@ -8319,7 +8349,7 @@ pub fn funcHasInferredErrorSet(ip: *const InternPool, i: Index) bool {
8319 return funcAnalysis(ip, i).inferred_error_set;8349 return funcAnalysis(ip, i).inferred_error_set;
8320}8350}
83218351
8322pub fn funcZirBodyInst(ip: *const InternPool, i: Index) Zir.Inst.Index {8352pub fn funcZirBodyInst(ip: *const InternPool, i: Index) TrackedInst.Index {
8323 assert(i != .none);8353 assert(i != .none);
8324 const item = ip.items.get(@intFromEnum(i));8354 const item = ip.items.get(@intFromEnum(i));
8325 const zir_body_inst_field_index = std.meta.fieldIndex(Tag.FuncDecl, "zir_body_inst").?;8355 const zir_body_inst_field_index = std.meta.fieldIndex(Tag.FuncDecl, "zir_body_inst").?;
src/Module.zig+246-342
...@@ -386,11 +386,9 @@ pub const Decl = struct {...@@ -386,11 +386,9 @@ pub const Decl = struct {
386 /// do not need to be loaded into memory in order to compute debug line numbers.386 /// do not need to be loaded into memory in order to compute debug line numbers.
387 /// This value is absolute.387 /// This value is absolute.
388 src_line: u32,388 src_line: u32,
389 /// Index to ZIR `extra` array to the entry in the parent's decl structure389 /// Index of the ZIR `declaration` instruction from which this `Decl` was created.
390 /// (the part that says "for every decls_len"). The first item at this index is390 /// For the root `Decl` of a `File` and legacy anonymous decls, this is `.none`.
391 /// the contents hash, followed by line, name, etc.391 zir_decl_index: Zir.Inst.OptionalIndex,
392 /// For anonymous decls and also the root Decl for a File, this is `none`.
393 zir_decl_index: Zir.OptionalExtraIndex,
394392
395 /// Represents the "shallow" analysis status. For example, for decls that are functions,393 /// Represents the "shallow" analysis status. For example, for decls that are functions,
396 /// the function type is analyzed with this set to `in_progress`, however, the semantic394 /// the function type is analyzed with this set to `in_progress`, however, the semantic
...@@ -442,10 +440,6 @@ pub const Decl = struct {...@@ -442,10 +440,6 @@ pub const Decl = struct {
442 is_pub: bool,440 is_pub: bool,
443 /// Whether the corresponding AST decl has a `export` keyword.441 /// Whether the corresponding AST decl has a `export` keyword.
444 is_exported: bool,442 is_exported: bool,
445 /// Whether the ZIR code provides an align instruction.
446 has_align: bool,
447 /// Whether the ZIR code provides a linksection and address space instruction.
448 has_linksection_or_addrspace: bool,
449 /// Flag used by garbage collection to mark and sweep.443 /// Flag used by garbage collection to mark and sweep.
450 /// Decls which correspond to an AST node always have this field set to `true`.444 /// Decls which correspond to an AST node always have this field set to `true`.
451 /// Anonymous Decls are initialized with this field set to `false` and then it445 /// Anonymous Decls are initialized with this field set to `false` and then it
...@@ -471,81 +465,19 @@ pub const Decl = struct {...@@ -471,81 +465,19 @@ pub const Decl = struct {
471 const Index = InternPool.DeclIndex;465 const Index = InternPool.DeclIndex;
472 const OptionalIndex = InternPool.OptionalDeclIndex;466 const OptionalIndex = InternPool.OptionalDeclIndex;
473467
474 pub const DepsTable = std.AutoArrayHashMapUnmanaged(Decl.Index, DepType);468 /// Asserts that `zir_decl_index` is not `.none`.
475469 fn getDeclaration(decl: Decl, zir: Zir) Zir.Inst.Declaration {
476 /// Later types take priority; e.g. if a dependent decl has both `normal`470 const zir_index = decl.zir_decl_index.unwrap().?;
477 /// and `function_body` dependencies on another decl, it will be marked as471 const pl_node = zir.instructions.items(.data)[@intFromEnum(zir_index)].pl_node;
478 /// having a `function_body` dependency.472 return zir.extraData(Zir.Inst.Declaration, pl_node.payload_index).data;
479 pub const DepType = enum {
480 /// The dependent references or uses the dependency's value, so must be
481 /// updated whenever it is changed. However, if the dependency is a
482 /// function and its type is unchanged, the dependent does not need to
483 /// be updated.
484 normal,
485 /// The dependent performs an inline or comptime call to the dependency,
486 /// or is a generic instantiation of it. It must therefore be updated
487 /// whenever the dependency is updated, even if the function type
488 /// remained the same.
489 function_body,
490 };
491
492 /// This name is relative to the containing namespace of the decl.
493 /// The memory is owned by the containing File ZIR.
494 pub fn getName(decl: Decl, mod: *Module) ?[:0]const u8 {
495 const zir = decl.getFileScope(mod).zir;
496 return decl.getNameZir(zir);
497 }
498
499 pub fn getNameZir(decl: Decl, zir: Zir) ?[:0]const u8 {
500 assert(decl.zir_decl_index != .none);
501 const name_index = zir.extra[@intFromEnum(decl.zir_decl_index) + 5];
502 if (name_index <= 1) return null;
503 return zir.nullTerminatedString(name_index);
504 }473 }
505474
506 pub fn contentsHash(decl: Decl, mod: *Module) std.zig.SrcHash {475 pub fn zirBodies(decl: Decl, zcu: *Zcu) Zir.Inst.Declaration.Bodies {
507 const zir = decl.getFileScope(mod).zir;476 const zir = decl.getFileScope(zcu).zir;
508 return decl.contentsHashZir(zir);477 const zir_index = decl.zir_decl_index.unwrap().?;
509 }478 const pl_node = zir.instructions.items(.data)[@intFromEnum(zir_index)].pl_node;
510479 const extra = zir.extraData(Zir.Inst.Declaration, pl_node.payload_index);
511 pub fn contentsHashZir(decl: Decl, zir: Zir) std.zig.SrcHash {480 return extra.data.getBodies(@intCast(extra.end), zir);
512 assert(decl.zir_decl_index != .none);
513 const hash_u32s = zir.extra[@intFromEnum(decl.zir_decl_index)..][0..4];
514 const contents_hash = @as(std.zig.SrcHash, @bitCast(hash_u32s.*));
515 return contents_hash;
516 }
517
518 pub fn zirBlockIndex(decl: *const Decl, mod: *Module) Zir.Inst.Index {
519 assert(decl.zir_decl_index != .none);
520 const zir = decl.getFileScope(mod).zir;
521 return @enumFromInt(zir.extra[@intFromEnum(decl.zir_decl_index) + 6]);
522 }
523
524 pub fn zirAlignRef(decl: Decl, mod: *Module) Zir.Inst.Ref {
525 if (!decl.has_align) return .none;
526 assert(decl.zir_decl_index != .none);
527 const zir = decl.getFileScope(mod).zir;
528 return @enumFromInt(zir.extra[@intFromEnum(decl.zir_decl_index) + 8]);
529 }
530
531 pub fn zirLinksectionRef(decl: Decl, mod: *Module) Zir.Inst.Ref {
532 if (!decl.has_linksection_or_addrspace) return .none;
533 assert(decl.zir_decl_index != .none);
534 const zir = decl.getFileScope(mod).zir;
535 const extra_index = @intFromEnum(decl.zir_decl_index) + 8 + @intFromBool(decl.has_align);
536 return @enumFromInt(zir.extra[extra_index]);
537 }
538
539 pub fn zirAddrspaceRef(decl: Decl, mod: *Module) Zir.Inst.Ref {
540 if (!decl.has_linksection_or_addrspace) return .none;
541 assert(decl.zir_decl_index != .none);
542 const zir = decl.getFileScope(mod).zir;
543 const extra_index = @intFromEnum(decl.zir_decl_index) + 8 + @intFromBool(decl.has_align) + 1;
544 return @enumFromInt(zir.extra[extra_index]);
545 }
546
547 pub fn relativeToLine(decl: Decl, offset: u32) u32 {
548 return decl.src_line + offset;
549 }481 }
550482
551 pub fn relativeToNodeIndex(decl: Decl, offset: i32) Ast.Node.Index {483 pub fn relativeToNodeIndex(decl: Decl, offset: i32) Ast.Node.Index {
...@@ -902,6 +834,9 @@ pub const File = struct {...@@ -902,6 +834,9 @@ pub const File = struct {
902 multi_pkg: bool = false,834 multi_pkg: bool = false,
903 /// List of references to this file, used for multi-package errors.835 /// List of references to this file, used for multi-package errors.
904 references: std.ArrayListUnmanaged(Reference) = .{},836 references: std.ArrayListUnmanaged(Reference) = .{},
837 /// The hash of the path to this file, used to store `InternPool.TrackedInst`.
838 /// undefined until `zir_loaded == true`.
839 path_digest: Cache.BinDigest = undefined,
905840
906 /// Used by change detection algorithm, after astgen, contains the841 /// Used by change detection algorithm, after astgen, contains the
907 /// set of decls that existed in the previous ZIR but not in the new one.842 /// set of decls that existed in the previous ZIR but not in the new one.
...@@ -2662,7 +2597,7 @@ pub fn astGenFile(mod: *Module, file: *File) !void {...@@ -2662,7 +2597,7 @@ pub fn astGenFile(mod: *Module, file: *File) !void {
2662 const stat = try source_file.stat();2597 const stat = try source_file.stat();
26632598
2664 const want_local_cache = file.mod == mod.main_mod;2599 const want_local_cache = file.mod == mod.main_mod;
2665 const digest = hash: {2600 const bin_digest = hash: {
2666 var path_hash: Cache.HashHelper = .{};2601 var path_hash: Cache.HashHelper = .{};
2667 path_hash.addBytes(build_options.version);2602 path_hash.addBytes(build_options.version);
2668 path_hash.add(builtin.zig_backend);2603 path_hash.add(builtin.zig_backend);
...@@ -2671,7 +2606,19 @@ pub fn astGenFile(mod: *Module, file: *File) !void {...@@ -2671,7 +2606,19 @@ pub fn astGenFile(mod: *Module, file: *File) !void {
2671 path_hash.addBytes(file.mod.root.sub_path);2606 path_hash.addBytes(file.mod.root.sub_path);
2672 }2607 }
2673 path_hash.addBytes(file.sub_file_path);2608 path_hash.addBytes(file.sub_file_path);
2674 break :hash path_hash.final();2609 var bin: Cache.BinDigest = undefined;
2610 path_hash.hasher.final(&bin);
2611 break :hash bin;
2612 };
2613 file.path_digest = bin_digest;
2614 const hex_digest = hex: {
2615 var hex: Cache.HexDigest = undefined;
2616 _ = std.fmt.bufPrint(
2617 &hex,
2618 "{s}",
2619 .{std.fmt.fmtSliceHexLower(&bin_digest)},
2620 ) catch unreachable;
2621 break :hex hex;
2675 };2622 };
2676 const cache_directory = if (want_local_cache) mod.local_zir_cache else mod.global_zir_cache;2623 const cache_directory = if (want_local_cache) mod.local_zir_cache else mod.global_zir_cache;
2677 const zir_dir = cache_directory.handle;2624 const zir_dir = cache_directory.handle;
...@@ -2681,7 +2628,7 @@ pub fn astGenFile(mod: *Module, file: *File) !void {...@@ -2681,7 +2628,7 @@ pub fn astGenFile(mod: *Module, file: *File) !void {
2681 .never_loaded, .retryable_failure => lock: {2628 .never_loaded, .retryable_failure => lock: {
2682 // First, load the cached ZIR code, if any.2629 // First, load the cached ZIR code, if any.
2683 log.debug("AstGen checking cache: {s} (local={}, digest={s})", .{2630 log.debug("AstGen checking cache: {s} (local={}, digest={s})", .{
2684 file.sub_file_path, want_local_cache, &digest,2631 file.sub_file_path, want_local_cache, &hex_digest,
2685 });2632 });
26862633
2687 break :lock .shared;2634 break :lock .shared;
...@@ -2708,7 +2655,7 @@ pub fn astGenFile(mod: *Module, file: *File) !void {...@@ -2708,7 +2655,7 @@ pub fn astGenFile(mod: *Module, file: *File) !void {
2708 // version. Likewise if we're working on AstGen and another process asks for2655 // version. Likewise if we're working on AstGen and another process asks for
2709 // the cached file, they'll get it.2656 // the cached file, they'll get it.
2710 const cache_file = while (true) {2657 const cache_file = while (true) {
2711 break zir_dir.createFile(&digest, .{2658 break zir_dir.createFile(&hex_digest, .{
2712 .read = true,2659 .read = true,
2713 .truncate = false,2660 .truncate = false,
2714 .lock = lock,2661 .lock = lock,
...@@ -2894,7 +2841,7 @@ pub fn astGenFile(mod: *Module, file: *File) !void {...@@ -2894,7 +2841,7 @@ pub fn astGenFile(mod: *Module, file: *File) !void {
2894 };2841 };
2895 cache_file.writevAll(&iovecs) catch |err| {2842 cache_file.writevAll(&iovecs) catch |err| {
2896 log.warn("unable to write cached ZIR code for {}{s} to {}{s}: {s}", .{2843 log.warn("unable to write cached ZIR code for {}{s} to {}{s}: {s}", .{
2897 file.mod.root, file.sub_file_path, cache_directory, &digest, @errorName(err),2844 file.mod.root, file.sub_file_path, cache_directory, &hex_digest, @errorName(err),
2898 });2845 });
2899 };2846 };
29002847
...@@ -3003,93 +2950,22 @@ fn loadZirCacheBody(gpa: Allocator, header: Zir.Header, cache_file: std.fs.File)...@@ -3003,93 +2950,22 @@ fn loadZirCacheBody(gpa: Allocator, header: Zir.Header, cache_file: std.fs.File)
3003 return zir;2950 return zir;
3004}2951}
30052952
3006/// Patch ups:2953fn updateZirRefs(zcu: *Module, file: *File, old_zir: Zir) !void {
3007/// * Struct.zir_index2954 const gpa = zcu.gpa;
3008/// * Decl.zir_index
3009/// * Fn.zir_body_inst
3010/// * Decl.zir_decl_index
3011fn updateZirRefs(mod: *Module, file: *File, old_zir: Zir) !void {
3012 const gpa = mod.gpa;
3013 const new_zir = file.zir;
3014
3015 // The root decl will be null if the previous ZIR had AST errors.
3016 const root_decl = file.root_decl.unwrap() orelse return;
30172955
3018 // Maps from old ZIR to new ZIR, struct_decl, enum_decl, etc. Any instruction which
3019 // creates a namespace, gets mapped from old to new here.
3020 var inst_map: std.AutoHashMapUnmanaged(Zir.Inst.Index, Zir.Inst.Index) = .{};2956 var inst_map: std.AutoHashMapUnmanaged(Zir.Inst.Index, Zir.Inst.Index) = .{};
3021 defer inst_map.deinit(gpa);2957 defer inst_map.deinit(gpa);
3022 // Maps from old ZIR to new ZIR, the extra data index for the sub-decl item.
3023 // e.g. the thing that Decl.zir_decl_index points to.
3024 var extra_map: std.AutoHashMapUnmanaged(Zir.ExtraIndex, Zir.ExtraIndex) = .{};
3025 defer extra_map.deinit(gpa);
3026
3027 try mapOldZirToNew(gpa, old_zir, new_zir, &inst_map, &extra_map);
3028
3029 // Walk the Decl graph, updating ZIR indexes, strings, and populating
3030 // the deleted and outdated lists.
3031
3032 var decl_stack: ArrayListUnmanaged(Decl.Index) = .{};
3033 defer decl_stack.deinit(gpa);
3034
3035 try decl_stack.append(gpa, root_decl);
3036
3037 file.deleted_decls.clearRetainingCapacity();
3038 file.outdated_decls.clearRetainingCapacity();
30392958
3040 // The root decl is always outdated; otherwise we would not have had2959 try mapOldZirToNew(gpa, old_zir, file.zir, &inst_map);
3041 // to re-generate ZIR for the File.
3042 try file.outdated_decls.append(gpa, root_decl);
30432960
3044 const ip = &mod.intern_pool;2961 // TODO: this should be done after all AstGen workers complete, to avoid
30452962 // iterating over this full set for every updated file.
3046 while (decl_stack.popOrNull()) |decl_index| {2963 for (zcu.intern_pool.tracked_insts.keys()) |*ti| {
3047 const decl = mod.declPtr(decl_index);2964 if (!std.mem.eql(u8, &ti.path_digest, &file.path_digest)) continue;
3048 // Anonymous decls and the root decl have this set to 0. We still need2965 ti.inst = inst_map.get(ti.inst) orelse {
3049 // to walk them but we do not need to modify this value.2966 // TODO: invalidate this `TrackedInst` via the dependency mechanism
3050 // Anonymous decls should not be marked outdated. They will be re-generated2967 continue;
3051 // if their owner decl is marked outdated.2968 };
3052 if (decl.zir_decl_index.unwrap()) |old_zir_decl_index| {
3053 const new_zir_decl_index = extra_map.get(old_zir_decl_index) orelse {
3054 try file.deleted_decls.append(gpa, decl_index);
3055 continue;
3056 };
3057 const old_hash = decl.contentsHashZir(old_zir);
3058 decl.zir_decl_index = new_zir_decl_index.toOptional();
3059 const new_hash = decl.contentsHashZir(new_zir);
3060 if (!std.zig.srcHashEql(old_hash, new_hash)) {
3061 try file.outdated_decls.append(gpa, decl_index);
3062 }
3063 }
3064
3065 if (!decl.owns_tv) continue;
3066
3067 if (decl.getOwnedStruct(mod)) |struct_type| {
3068 struct_type.setZirIndex(ip, inst_map.get(struct_type.zir_index) orelse {
3069 try file.deleted_decls.append(gpa, decl_index);
3070 continue;
3071 });
3072 }
3073
3074 if (decl.getOwnedUnion(mod)) |union_type| {
3075 union_type.setZirIndex(ip, inst_map.get(union_type.zir_index) orelse {
3076 try file.deleted_decls.append(gpa, decl_index);
3077 continue;
3078 });
3079 }
3080
3081 if (decl.getOwnedFunction(mod)) |func| {
3082 func.zirBodyInst(ip).* = inst_map.get(func.zir_body_inst) orelse {
3083 try file.deleted_decls.append(gpa, decl_index);
3084 continue;
3085 };
3086 }
3087
3088 if (decl.getOwnedInnerNamespace(mod)) |namespace| {
3089 for (namespace.decls.keys()) |sub_decl| {
3090 try decl_stack.append(gpa, sub_decl);
3091 }
3092 }
3093 }2969 }
3094}2970}
30952971
...@@ -3098,9 +2974,9 @@ pub fn mapOldZirToNew(...@@ -3098,9 +2974,9 @@ pub fn mapOldZirToNew(
3098 old_zir: Zir,2974 old_zir: Zir,
3099 new_zir: Zir,2975 new_zir: Zir,
3100 inst_map: *std.AutoHashMapUnmanaged(Zir.Inst.Index, Zir.Inst.Index),2976 inst_map: *std.AutoHashMapUnmanaged(Zir.Inst.Index, Zir.Inst.Index),
3101 extra_map: *std.AutoHashMapUnmanaged(Zir.ExtraIndex, Zir.ExtraIndex),
3102) Allocator.Error!void {2977) Allocator.Error!void {
3103 // Contain ZIR indexes of declaration instructions.2978 // Contain ZIR indexes of namespace declaration instructions, e.g. struct_decl, union_decl, etc.
2979 // Not `declaration`, as this does not create a namespace.
3104 const MatchedZirDecl = struct {2980 const MatchedZirDecl = struct {
3105 old_inst: Zir.Inst.Index,2981 old_inst: Zir.Inst.Index,
3106 new_inst: Zir.Inst.Index,2982 new_inst: Zir.Inst.Index,
...@@ -3108,47 +2984,113 @@ pub fn mapOldZirToNew(...@@ -3108,47 +2984,113 @@ pub fn mapOldZirToNew(
3108 var match_stack: ArrayListUnmanaged(MatchedZirDecl) = .{};2984 var match_stack: ArrayListUnmanaged(MatchedZirDecl) = .{};
3109 defer match_stack.deinit(gpa);2985 defer match_stack.deinit(gpa);
31102986
3111 // Main struct inst is always the same2987 // Main struct inst is always matched
3112 try match_stack.append(gpa, .{2988 try match_stack.append(gpa, .{
3113 .old_inst = .main_struct_inst,2989 .old_inst = .main_struct_inst,
3114 .new_inst = .main_struct_inst,2990 .new_inst = .main_struct_inst,
3115 });2991 });
31162992
2993 // Used as temporary buffers for namespace declaration instructions
3117 var old_decls = std.ArrayList(Zir.Inst.Index).init(gpa);2994 var old_decls = std.ArrayList(Zir.Inst.Index).init(gpa);
3118 defer old_decls.deinit();2995 defer old_decls.deinit();
3119 var new_decls = std.ArrayList(Zir.Inst.Index).init(gpa);2996 var new_decls = std.ArrayList(Zir.Inst.Index).init(gpa);
3120 defer new_decls.deinit();2997 defer new_decls.deinit();
31212998
3122 while (match_stack.popOrNull()) |match_item| {2999 while (match_stack.popOrNull()) |match_item| {
3000 // Match the namespace declaration itself
3123 try inst_map.put(gpa, match_item.old_inst, match_item.new_inst);3001 try inst_map.put(gpa, match_item.old_inst, match_item.new_inst);
31243002
3125 // Maps name to extra index of decl sub item.3003 // Maps decl name to `declaration` instruction.
3126 var decl_map: std.StringHashMapUnmanaged(Zir.ExtraIndex) = .{};3004 var named_decls: std.StringHashMapUnmanaged(Zir.Inst.Index) = .{};
3127 defer decl_map.deinit(gpa);3005 defer named_decls.deinit(gpa);
3006 // Maps test name to `declaration` instruction.
3007 var named_tests: std.StringHashMapUnmanaged(Zir.Inst.Index) = .{};
3008 defer named_tests.deinit(gpa);
3009 // All unnamed tests, in order, for a best-effort match.
3010 var unnamed_tests: std.ArrayListUnmanaged(Zir.Inst.Index) = .{};
3011 defer unnamed_tests.deinit(gpa);
3012 // All comptime declarations, in order, for a best-effort match.
3013 var comptime_decls: std.ArrayListUnmanaged(Zir.Inst.Index) = .{};
3014 defer comptime_decls.deinit(gpa);
3015 // All usingnamespace declarations, in order, for a best-effort match.
3016 var usingnamespace_decls: std.ArrayListUnmanaged(Zir.Inst.Index) = .{};
3017 defer usingnamespace_decls.deinit(gpa);
31283018
3129 {3019 {
3130 var old_decl_it = old_zir.declIterator(match_item.old_inst);3020 var old_decl_it = old_zir.declIterator(match_item.old_inst);
3131 while (old_decl_it.next()) |old_decl| {3021 while (old_decl_it.next()) |old_decl_inst| {
3132 try decl_map.put(gpa, old_decl.name, old_decl.sub_index);3022 const old_decl, _ = old_zir.getDeclaration(old_decl_inst);
3023 switch (old_decl.name) {
3024 .@"comptime" => try comptime_decls.append(gpa, old_decl_inst),
3025 .@"usingnamespace" => try usingnamespace_decls.append(gpa, old_decl_inst),
3026 .unnamed_test, .decltest => try unnamed_tests.append(gpa, old_decl_inst),
3027 _ => {
3028 const name_nts = old_decl.name.toString(old_zir).?;
3029 const name = old_zir.nullTerminatedString(name_nts);
3030 if (old_decl.name.isNamedTest(old_zir)) {
3031 try named_tests.put(gpa, name, old_decl_inst);
3032 } else {
3033 try named_decls.put(gpa, name, old_decl_inst);
3034 }
3035 },
3036 }
3133 }3037 }
3134 }3038 }
31353039
3040 var unnamed_test_idx: u32 = 0;
3041 var comptime_decl_idx: u32 = 0;
3042 var usingnamespace_decl_idx: u32 = 0;
3043
3136 var new_decl_it = new_zir.declIterator(match_item.new_inst);3044 var new_decl_it = new_zir.declIterator(match_item.new_inst);
3137 while (new_decl_it.next()) |new_decl| {3045 while (new_decl_it.next()) |new_decl_inst| {
3138 const old_extra_index = decl_map.get(new_decl.name) orelse continue;3046 const new_decl, _ = new_zir.getDeclaration(new_decl_inst);
3139 const new_extra_index = new_decl.sub_index;3047 // Attempt to match this to a declaration in the old ZIR:
3140 try extra_map.put(gpa, old_extra_index, new_extra_index);3048 // * For named declarations (`const`/`var`/`fn`), we match based on name.
31413049 // * For named tests (`test "foo"`), we also match based on name.
3142 try old_zir.findDecls(&old_decls, old_extra_index);3050 // * For unnamed tests and decltests, we match based on order.
3143 try new_zir.findDecls(&new_decls, new_extra_index);3051 // * For comptime blocks, we match based on order.
3144 var i: usize = 0;3052 // * For usingnamespace decls, we match based on order.
3145 while (true) : (i += 1) {3053 // If we cannot match this declaration, we can't match anything nested inside of it either, so we just `continue`.
3146 if (i >= old_decls.items.len) break;3054 const old_decl_inst = switch (new_decl.name) {
3147 if (i >= new_decls.items.len) break;3055 .@"comptime" => inst: {
3148 try match_stack.append(gpa, .{3056 if (comptime_decl_idx == comptime_decls.items.len) continue;
3149 .old_inst = old_decls.items[i],3057 defer comptime_decl_idx += 1;
3150 .new_inst = new_decls.items[i],3058 break :inst comptime_decls.items[comptime_decl_idx];
3151 });3059 },
3060 .@"usingnamespace" => inst: {
3061 if (usingnamespace_decl_idx == usingnamespace_decls.items.len) continue;
3062 defer usingnamespace_decl_idx += 1;
3063 break :inst usingnamespace_decls.items[usingnamespace_decl_idx];
3064 },
3065 .unnamed_test, .decltest => inst: {
3066 if (unnamed_test_idx == unnamed_tests.items.len) continue;
3067 defer unnamed_test_idx += 1;
3068 break :inst unnamed_tests.items[unnamed_test_idx];
3069 },
3070 _ => inst: {
3071 const name_nts = new_decl.name.toString(old_zir).?;
3072 const name = new_zir.nullTerminatedString(name_nts);
3073 if (new_decl.name.isNamedTest(new_zir)) {
3074 break :inst named_tests.get(name) orelse continue;
3075 } else {
3076 break :inst named_decls.get(name) orelse continue;
3077 }
3078 },
3079 };
3080
3081 // Match the `declaration` instruction
3082 try inst_map.put(gpa, old_decl_inst, new_decl_inst);
3083
3084 // Find namespace declarations within this declaration
3085 try old_zir.findDecls(&old_decls, old_decl_inst);
3086 try new_zir.findDecls(&new_decls, new_decl_inst);
3087
3088 // We don't have any smart way of matching up these namespace declarations, so we always
3089 // correlate them based on source order.
3090 const n = @min(old_decls.items.len, new_decls.items.len);
3091 try match_stack.ensureUnusedCapacity(gpa, n);
3092 for (old_decls.items[0..n], new_decls.items[0..n]) |old_inst, new_inst| {
3093 match_stack.appendAssumeCapacity(.{ .old_inst = old_inst, .new_inst = new_inst });
3152 }3094 }
3153 }3095 }
3154 }3096 }
...@@ -3457,8 +3399,6 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void {...@@ -3457,8 +3399,6 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void {
3457 new_decl.src_line = 0;3399 new_decl.src_line = 0;
3458 new_decl.is_pub = true;3400 new_decl.is_pub = true;
3459 new_decl.is_exported = false;3401 new_decl.is_exported = false;
3460 new_decl.has_align = false;
3461 new_decl.has_linksection_or_addrspace = false;
3462 new_decl.ty = Type.type;3402 new_decl.ty = Type.type;
3463 new_decl.alignment = .none;3403 new_decl.alignment = .none;
3464 new_decl.@"linksection" = .none;3404 new_decl.@"linksection" = .none;
...@@ -3502,7 +3442,7 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void {...@@ -3502,7 +3442,7 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void {
3502 const struct_ty = sema.getStructType(3442 const struct_ty = sema.getStructType(
3503 new_decl_index,3443 new_decl_index,
3504 new_namespace_index,3444 new_namespace_index,
3505 .main_struct_inst,3445 try mod.intern_pool.trackZir(gpa, file, .main_struct_inst),
3506 ) catch |err| switch (err) {3446 ) catch |err| switch (err) {
3507 error.OutOfMemory => return error.OutOfMemory,3447 error.OutOfMemory => return error.OutOfMemory,
3508 };3448 };
...@@ -3561,7 +3501,6 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {...@@ -3561,7 +3501,6 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
35613501
3562 const gpa = mod.gpa;3502 const gpa = mod.gpa;
3563 const zir = decl.getFileScope(mod).zir;3503 const zir = decl.getFileScope(mod).zir;
3564 const zir_datas = zir.instructions.items(.data);
35653504
3566 const builtin_type_target_index: InternPool.Index = blk: {3505 const builtin_type_target_index: InternPool.Index = blk: {
3567 const std_mod = mod.std_mod;3506 const std_mod = mod.std_mod;
...@@ -3639,11 +3578,9 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {...@@ -3639,11 +3578,9 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
3639 };3578 };
3640 defer block_scope.instructions.deinit(gpa);3579 defer block_scope.instructions.deinit(gpa);
36413580
3642 const zir_block_index = decl.zirBlockIndex(mod);3581 const decl_bodies = decl.zirBodies(mod);
3643 const inst_data = zir_datas[@intFromEnum(zir_block_index)].pl_node;3582
3644 const extra = zir.extraData(Zir.Inst.Block, inst_data.payload_index);3583 const result_ref = (try sema.analyzeBodyBreak(&block_scope, decl_bodies.value_body)).?.operand;
3645 const body = zir.extra[extra.end..][0..extra.data.body_len];
3646 const result_ref = (try sema.analyzeBodyBreak(&block_scope, @ptrCast(body))).?.operand;
3647 // We'll do some other bits with the Sema. Clear the type target index just3584 // We'll do some other bits with the Sema. Clear the type target index just
3648 // in case they analyze any type.3585 // in case they analyze any type.
3649 sema.builtin_type_target_index = .none;3586 sema.builtin_type_target_index = .none;
...@@ -3760,13 +3697,13 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {...@@ -3760,13 +3697,13 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
3760 decl.ty = decl_tv.ty;3697 decl.ty = decl_tv.ty;
3761 decl.val = Value.fromInterned((try decl_tv.val.intern(decl_tv.ty, mod)));3698 decl.val = Value.fromInterned((try decl_tv.val.intern(decl_tv.ty, mod)));
3762 decl.alignment = blk: {3699 decl.alignment = blk: {
3763 const align_ref = decl.zirAlignRef(mod);3700 const align_body = decl_bodies.align_body orelse break :blk .none;
3764 if (align_ref == .none) break :blk .none;3701 const align_ref = (try sema.analyzeBodyBreak(&block_scope, align_body)).?.operand;
3765 break :blk try sema.resolveAlign(&block_scope, align_src, align_ref);3702 break :blk try sema.resolveAlign(&block_scope, align_src, align_ref);
3766 };3703 };
3767 decl.@"linksection" = blk: {3704 decl.@"linksection" = blk: {
3768 const linksection_ref = decl.zirLinksectionRef(mod);3705 const linksection_body = decl_bodies.linksection_body orelse break :blk .none;
3769 if (linksection_ref == .none) break :blk .none;3706 const linksection_ref = (try sema.analyzeBodyBreak(&block_scope, linksection_body)).?.operand;
3770 const bytes = try sema.resolveConstString(&block_scope, section_src, linksection_ref, .{3707 const bytes = try sema.resolveConstString(&block_scope, section_src, linksection_ref, .{
3771 .needed_comptime_reason = "linksection must be comptime-known",3708 .needed_comptime_reason = "linksection must be comptime-known",
3772 });3709 });
...@@ -3786,15 +3723,15 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {...@@ -3786,15 +3723,15 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
3786 };3723 };
37873724
3788 const target = sema.mod.getTarget();3725 const target = sema.mod.getTarget();
3789 break :blk switch (decl.zirAddrspaceRef(mod)) {3726
3790 .none => switch (addrspace_ctx) {3727 const addrspace_body = decl_bodies.addrspace_body orelse break :blk switch (addrspace_ctx) {
3791 .function => target_util.defaultAddressSpace(target, .function),3728 .function => target_util.defaultAddressSpace(target, .function),
3792 .variable => target_util.defaultAddressSpace(target, .global_mutable),3729 .variable => target_util.defaultAddressSpace(target, .global_mutable),
3793 .constant => target_util.defaultAddressSpace(target, .global_constant),3730 .constant => target_util.defaultAddressSpace(target, .global_constant),
3794 else => unreachable,3731 else => unreachable,
3795 },
3796 else => |addrspace_ref| try sema.analyzeAddressSpace(&block_scope, address_space_src, addrspace_ref, addrspace_ctx),
3797 };3732 };
3733 const addrspace_ref = (try sema.analyzeBodyBreak(&block_scope, addrspace_body)).?.operand;
3734 break :blk try sema.analyzeAddressSpace(&block_scope, address_space_src, addrspace_ref, addrspace_ctx);
3798 };3735 };
3799 decl.has_tv = true;3736 decl.has_tv = true;
3800 decl.analysis = .complete;3737 decl.analysis = .complete;
...@@ -4133,52 +4070,32 @@ fn newEmbedFile(...@@ -4133,52 +4070,32 @@ fn newEmbedFile(
4133}4070}
41344071
4135pub fn scanNamespace(4072pub fn scanNamespace(
4136 mod: *Module,4073 zcu: *Zcu,
4137 namespace_index: Namespace.Index,4074 namespace_index: Namespace.Index,
4138 extra_start: usize,4075 decls: []const Zir.Inst.Index,
4139 decls_len: u32,
4140 parent_decl: *Decl,4076 parent_decl: *Decl,
4141) Allocator.Error!usize {4077) Allocator.Error!void {
4142 const tracy = trace(@src());4078 const tracy = trace(@src());
4143 defer tracy.end();4079 defer tracy.end();
41444080
4145 const gpa = mod.gpa;4081 const gpa = zcu.gpa;
4146 const namespace = mod.namespacePtr(namespace_index);4082 const namespace = zcu.namespacePtr(namespace_index);
4147 const zir = namespace.file_scope.zir;
41484083
4149 try mod.comp.work_queue.ensureUnusedCapacity(decls_len);4084 try zcu.comp.work_queue.ensureUnusedCapacity(decls.len);
4150 try namespace.decls.ensureTotalCapacity(gpa, decls_len);4085 try namespace.decls.ensureTotalCapacity(gpa, decls.len);
41514086
4152 const bit_bags_count = std.math.divCeil(usize, decls_len, 8) catch unreachable;
4153 var extra_index = extra_start + bit_bags_count;
4154 var bit_bag_index: usize = extra_start;
4155 var cur_bit_bag: u32 = undefined;
4156 var decl_i: u32 = 0;
4157 var scan_decl_iter: ScanDeclIter = .{4087 var scan_decl_iter: ScanDeclIter = .{
4158 .module = mod,4088 .zcu = zcu,
4159 .namespace_index = namespace_index,4089 .namespace_index = namespace_index,
4160 .parent_decl = parent_decl,4090 .parent_decl = parent_decl,
4161 };4091 };
4162 while (decl_i < decls_len) : (decl_i += 1) {4092 for (decls) |decl_inst| {
4163 if (decl_i % 8 == 0) {4093 try scanDecl(&scan_decl_iter, decl_inst);
4164 cur_bit_bag = zir.extra[bit_bag_index];
4165 bit_bag_index += 1;
4166 }
4167 const flags = @as(u4, @truncate(cur_bit_bag));
4168 cur_bit_bag >>= 4;
4169
4170 const decl_sub_index = extra_index;
4171 extra_index += 8; // src_hash(4) + line(1) + name(1) + value(1) + doc_comment(1)
4172 extra_index += @as(u1, @truncate(flags >> 2)); // Align
4173 extra_index += @as(u2, @as(u1, @truncate(flags >> 3))) * 2; // Link section or address space, consists of 2 Refs
4174
4175 try scanDecl(&scan_decl_iter, decl_sub_index, flags);
4176 }4094 }
4177 return extra_index;
4178}4095}
41794096
4180const ScanDeclIter = struct {4097const ScanDeclIter = struct {
4181 module: *Module,4098 zcu: *Zcu,
4182 namespace_index: Namespace.Index,4099 namespace_index: Namespace.Index,
4183 parent_decl: *Decl,4100 parent_decl: *Decl,
4184 usingnamespace_index: usize = 0,4101 usingnamespace_index: usize = 0,
...@@ -4186,119 +4103,112 @@ const ScanDeclIter = struct {...@@ -4186,119 +4103,112 @@ const ScanDeclIter = struct {
4186 unnamed_test_index: usize = 0,4103 unnamed_test_index: usize = 0,
4187};4104};
41884105
4189fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Error!void {4106fn scanDecl(iter: *ScanDeclIter, decl_inst: Zir.Inst.Index) Allocator.Error!void {
4190 const tracy = trace(@src());4107 const tracy = trace(@src());
4191 defer tracy.end();4108 defer tracy.end();
41924109
4193 const mod = iter.module;4110 const zcu = iter.zcu;
4194 const namespace_index = iter.namespace_index;4111 const namespace_index = iter.namespace_index;
4195 const namespace = mod.namespacePtr(namespace_index);4112 const namespace = zcu.namespacePtr(namespace_index);
4196 const gpa = mod.gpa;4113 const gpa = zcu.gpa;
4197 const zir = namespace.file_scope.zir;4114 const zir = namespace.file_scope.zir;
4198 const ip = &mod.intern_pool;4115 const ip = &zcu.intern_pool;
4116
4117 const pl_node = zir.instructions.items(.data)[@intFromEnum(decl_inst)].pl_node;
4118 const extra = zir.extraData(Zir.Inst.Declaration, pl_node.payload_index);
4119 const declaration = extra.data;
41994120
4200 // zig fmt: off4121 const line = iter.parent_decl.src_line + declaration.line_offset;
4201 const is_pub = (flags & 0b0001) != 0;4122 const decl_node = iter.parent_decl.relativeToNodeIndex(pl_node.src_node);
4202 const export_bit = (flags & 0b0010) != 0;
4203 const has_align = (flags & 0b0100) != 0;
4204 const has_linksection_or_addrspace = (flags & 0b1000) != 0;
4205 // zig fmt: on
4206
4207 const line_off = zir.extra[decl_sub_index + 4];
4208 const line = iter.parent_decl.relativeToLine(line_off);
4209 const decl_name_index: Zir.NullTerminatedString = @enumFromInt(zir.extra[decl_sub_index + 5]);
4210 const decl_doccomment_index = zir.extra[decl_sub_index + 7];
4211 const decl_zir_index = zir.extra[decl_sub_index + 6];
4212 const decl_block_inst_data = zir.instructions.items(.data)[decl_zir_index].pl_node;
4213 const decl_node = iter.parent_decl.relativeToNodeIndex(decl_block_inst_data.src_node);
42144123
4215 // Every Decl needs a name.4124 // Every Decl needs a name.
4216 var is_named_test = false;4125 const decl_name: InternPool.NullTerminatedString, const kind: Decl.Kind, const is_named_test: bool = switch (declaration.name) {
4217 var kind: Decl.Kind = .named;4126 .@"comptime" => info: {
4218 const decl_name: InternPool.NullTerminatedString = switch (decl_name_index) {4127 const i = iter.comptime_index;
4219 .empty => name: {4128 iter.comptime_index += 1;
4220 if (export_bit) {4129 break :info .{
4221 const i = iter.usingnamespace_index;4130 try ip.getOrPutStringFmt(gpa, "comptime_{d}", .{i}),
4222 iter.usingnamespace_index += 1;4131 .@"comptime",
4223 kind = .@"usingnamespace";4132 false,
4224 break :name try ip.getOrPutStringFmt(gpa, "usingnamespace_{d}", .{i});4133 };
4225 } else {
4226 const i = iter.comptime_index;
4227 iter.comptime_index += 1;
4228 kind = .@"comptime";
4229 break :name try ip.getOrPutStringFmt(gpa, "comptime_{d}", .{i});
4230 }
4231 },4134 },
4232 .unnamed_test_decl => name: {4135 .@"usingnamespace" => info: {
4136 const i = iter.usingnamespace_index;
4137 iter.usingnamespace_index += 1;
4138 break :info .{
4139 try ip.getOrPutStringFmt(gpa, "usingnamespace_{d}", .{i}),
4140 .@"usingnamespace",
4141 false,
4142 };
4143 },
4144 .unnamed_test => info: {
4233 const i = iter.unnamed_test_index;4145 const i = iter.unnamed_test_index;
4234 iter.unnamed_test_index += 1;4146 iter.unnamed_test_index += 1;
4235 kind = .@"test";4147 break :info .{
4236 break :name try ip.getOrPutStringFmt(gpa, "test_{d}", .{i});4148 try ip.getOrPutStringFmt(gpa, "test_{d}", .{i}),
4149 .@"test",
4150 false,
4151 };
4237 },4152 },
4238 .decltest => name: {4153 .decltest => info: {
4239 is_named_test = true;4154 assert(declaration.flags.has_doc_comment);
4240 const test_name = zir.nullTerminatedString(@enumFromInt(decl_doccomment_index));4155 const name = zir.nullTerminatedString(@enumFromInt(zir.extra[extra.end]));
4241 kind = .@"test";4156 break :info .{
4242 break :name try ip.getOrPutStringFmt(gpa, "decltest.{s}", .{test_name});4157 try ip.getOrPutStringFmt(gpa, "decltest.{s}", .{name}),
4158 .@"test",
4159 true,
4160 };
4243 },4161 },
4244 _ => name: {4162 _ => if (declaration.name.isNamedTest(zir)) .{
4245 const raw_name = zir.nullTerminatedString(decl_name_index);4163 try ip.getOrPutStringFmt(gpa, "test.{s}", .{zir.nullTerminatedString(declaration.name.toString(zir).?)}),
4246 if (raw_name.len == 0) {4164 .@"test",
4247 is_named_test = true;4165 true,
4248 const test_name = zir.nullTerminatedString(@enumFromInt(@intFromEnum(decl_name_index) + 1));4166 } else .{
4249 kind = .@"test";4167 try ip.getOrPutString(gpa, zir.nullTerminatedString(declaration.name.toString(zir).?)),
4250 break :name try ip.getOrPutStringFmt(gpa, "test.{s}", .{test_name});4168 .named,
4251 } else {4169 false,
4252 break :name try ip.getOrPutString(gpa, raw_name);
4253 }
4254 },4170 },
4255 };4171 };
42564172
4257 const is_exported = export_bit and decl_name_index != .empty;
4258 if (kind == .@"usingnamespace") try namespace.usingnamespace_set.ensureUnusedCapacity(gpa, 1);4173 if (kind == .@"usingnamespace") try namespace.usingnamespace_set.ensureUnusedCapacity(gpa, 1);
42594174
4260 // We create a Decl for it regardless of analysis status.4175 // We create a Decl for it regardless of analysis status.
4261 const gop = try namespace.decls.getOrPutContextAdapted(4176 const gop = try namespace.decls.getOrPutContextAdapted(
4262 gpa,4177 gpa,
4263 decl_name,4178 decl_name,
4264 DeclAdapter{ .mod = mod },4179 DeclAdapter{ .mod = zcu },
4265 Namespace.DeclContext{ .module = mod },4180 Namespace.DeclContext{ .module = zcu },
4266 );4181 );
4267 const comp = mod.comp;4182 const comp = zcu.comp;
4268 if (!gop.found_existing) {4183 if (!gop.found_existing) {
4269 const new_decl_index = try mod.allocateNewDecl(namespace_index, decl_node, iter.parent_decl.src_scope);4184 const new_decl_index = try zcu.allocateNewDecl(namespace_index, decl_node, iter.parent_decl.src_scope);
4270 const new_decl = mod.declPtr(new_decl_index);4185 const new_decl = zcu.declPtr(new_decl_index);
4271 new_decl.kind = kind;4186 new_decl.kind = kind;
4272 new_decl.name = decl_name;4187 new_decl.name = decl_name;
4273 if (kind == .@"usingnamespace") {4188 if (kind == .@"usingnamespace") {
4274 namespace.usingnamespace_set.putAssumeCapacity(new_decl_index, is_pub);4189 namespace.usingnamespace_set.putAssumeCapacity(new_decl_index, declaration.flags.is_pub);
4275 }4190 }
4276 new_decl.src_line = line;4191 new_decl.src_line = line;
4277 gop.key_ptr.* = new_decl_index;4192 gop.key_ptr.* = new_decl_index;
4278 // Exported decls, comptime decls, usingnamespace decls, and4193 // Exported decls, comptime decls, usingnamespace decls, and
4279 // test decls if in test mode, get analyzed.4194 // test decls if in test mode, get analyzed.
4280 const decl_mod = namespace.file_scope.mod;4195 const decl_mod = namespace.file_scope.mod;
4281 const want_analysis = is_exported or switch (decl_name_index) {4196 const want_analysis = declaration.flags.is_export or switch (kind) {
4282 .empty => true, // comptime or usingnamespace decl4197 .anon => unreachable,
4283 .unnamed_test_decl => blk: {4198 .@"comptime", .@"usingnamespace" => true,
4284 // test decl with no name. Skip the part where we check against4199 .named => false,
4285 // the test name filter.4200 .@"test" => a: {
4286 if (!comp.config.is_test) break :blk false;4201 if (!comp.config.is_test) break :a false;
4287 if (decl_mod != mod.main_mod) break :blk false;4202 if (decl_mod != zcu.main_mod) break :a false;
4288 try mod.test_functions.put(gpa, new_decl_index, {});4203 if (is_named_test) {
4289 break :blk true;4204 if (comp.test_filter) |test_filter| {
4290 },4205 if (mem.indexOf(u8, ip.stringToSlice(decl_name), test_filter) == null) {
4291 else => blk: {4206 break :a false;
4292 if (!is_named_test) break :blk false;4207 }
4293 if (!comp.config.is_test) break :blk false;
4294 if (decl_mod != mod.main_mod) break :blk false;
4295 if (comp.test_filter) |test_filter| {
4296 if (mem.indexOf(u8, ip.stringToSlice(decl_name), test_filter) == null) {
4297 break :blk false;
4298 }4208 }
4299 }4209 }
4300 try mod.test_functions.put(gpa, new_decl_index, {});4210 try zcu.test_functions.put(gpa, new_decl_index, {});
4301 break :blk true;4211 break :a true;
4302 },4212 },
4303 };4213 };
4304 if (want_analysis) {4214 if (want_analysis) {
...@@ -4307,46 +4217,42 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err...@@ -4307,46 +4217,42 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err
4307 });4217 });
4308 comp.work_queue.writeItemAssumeCapacity(.{ .analyze_decl = new_decl_index });4218 comp.work_queue.writeItemAssumeCapacity(.{ .analyze_decl = new_decl_index });
4309 }4219 }
4310 new_decl.is_pub = is_pub;4220 new_decl.is_pub = declaration.flags.is_pub;
4311 new_decl.is_exported = is_exported;4221 new_decl.is_exported = declaration.flags.is_export;
4312 new_decl.has_align = has_align;4222 new_decl.zir_decl_index = decl_inst.toOptional();
4313 new_decl.has_linksection_or_addrspace = has_linksection_or_addrspace;
4314 new_decl.zir_decl_index = @enumFromInt(decl_sub_index);
4315 new_decl.alive = true; // This Decl corresponds to an AST node and therefore always alive.4223 new_decl.alive = true; // This Decl corresponds to an AST node and therefore always alive.
4316 return;4224 return;
4317 }4225 }
4318 const decl_index = gop.key_ptr.*;4226 const decl_index = gop.key_ptr.*;
4319 const decl = mod.declPtr(decl_index);4227 const decl = zcu.declPtr(decl_index);
4320 if (kind == .@"test") {4228 if (kind == .@"test") {
4321 const src_loc = SrcLoc{4229 const src_loc = SrcLoc{
4322 .file_scope = decl.getFileScope(mod),4230 .file_scope = decl.getFileScope(zcu),
4323 .parent_decl_node = decl.src_node,4231 .parent_decl_node = decl.src_node,
4324 .lazy = .{ .token_offset = 1 },4232 .lazy = .{ .token_offset = 1 },
4325 };4233 };
4326 const msg = try ErrorMsg.create(gpa, src_loc, "duplicate test name: {}", .{4234 const msg = try ErrorMsg.create(gpa, src_loc, "duplicate test name: {}", .{
4327 decl_name.fmt(&mod.intern_pool),4235 decl_name.fmt(ip),
4328 });4236 });
4329 errdefer msg.destroy(gpa);4237 errdefer msg.destroy(gpa);
4330 try mod.failed_decls.putNoClobber(gpa, decl_index, msg);4238 try zcu.failed_decls.putNoClobber(gpa, decl_index, msg);
4331 const other_src_loc = SrcLoc{4239 const other_src_loc = SrcLoc{
4332 .file_scope = namespace.file_scope,4240 .file_scope = namespace.file_scope,
4333 .parent_decl_node = decl_node,4241 .parent_decl_node = decl_node,
4334 .lazy = .{ .token_offset = 1 },4242 .lazy = .{ .token_offset = 1 },
4335 };4243 };
4336 try mod.errNoteNonLazy(other_src_loc, msg, "other test here", .{});4244 try zcu.errNoteNonLazy(other_src_loc, msg, "other test here", .{});
4337 }4245 }
4338 // Update the AST node of the decl; even if its contents are unchanged, it may4246 // Update the AST node of the decl; even if its contents are unchanged, it may
4339 // have been re-ordered.4247 // have been re-ordered.
4340 decl.src_node = decl_node;4248 decl.src_node = decl_node;
4341 decl.src_line = line;4249 decl.src_line = line;
43424250
4343 decl.is_pub = is_pub;4251 decl.is_pub = declaration.flags.is_pub;
4344 decl.is_exported = is_exported;4252 decl.is_exported = declaration.flags.is_export;
4345 decl.kind = kind;4253 decl.kind = kind;
4346 decl.has_align = has_align;4254 decl.zir_decl_index = decl_inst.toOptional();
4347 decl.has_linksection_or_addrspace = has_linksection_or_addrspace;4255 if (decl.getOwnedFunction(zcu) != null) {
4348 decl.zir_decl_index = @enumFromInt(decl_sub_index);
4349 if (decl.getOwnedFunction(mod) != null) {
4350 // TODO Look into detecting when this would be unnecessary by storing enough state4256 // TODO Look into detecting when this would be unnecessary by storing enough state
4351 // in `Decl` to notice that the line number did not change.4257 // in `Decl` to notice that the line number did not change.
4352 comp.work_queue.writeItemAssumeCapacity(.{ .update_line_number = decl_index });4258 comp.work_queue.writeItemAssumeCapacity(.{ .update_line_number = decl_index });
...@@ -4514,7 +4420,7 @@ pub fn analyzeFnBody(mod: *Module, func_index: InternPool.Index, arena: Allocato...@@ -4514,7 +4420,7 @@ pub fn analyzeFnBody(mod: *Module, func_index: InternPool.Index, arena: Allocato
4514 };4420 };
4515 defer inner_block.instructions.deinit(gpa);4421 defer inner_block.instructions.deinit(gpa);
45164422
4517 const fn_info = sema.code.getFnInfo(func.zirBodyInst(ip).*);4423 const fn_info = sema.code.getFnInfo(func.zirBodyInst(ip).resolve(ip));
45184424
4519 // Here we are performing "runtime semantic analysis" for a function body, which means4425 // Here we are performing "runtime semantic analysis" for a function body, which means
4520 // we must map the parameter ZIR instructions to `arg` AIR instructions.4426 // we must map the parameter ZIR instructions to `arg` AIR instructions.
...@@ -4730,8 +4636,6 @@ pub fn allocateNewDecl(...@@ -4730,8 +4636,6 @@ pub fn allocateNewDecl(
4730 .generation = 0,4636 .generation = 0,
4731 .is_pub = false,4637 .is_pub = false,
4732 .is_exported = false,4638 .is_exported = false,
4733 .has_linksection_or_addrspace = false,
4734 .has_align = false,
4735 .alive = false,4639 .alive = false,
4736 .kind = .anon,4640 .kind = .anon,
4737 });4641 });
...@@ -6169,7 +6073,7 @@ pub fn getParamName(mod: *Module, func_index: InternPool.Index, index: u32) [:0]...@@ -6169,7 +6073,7 @@ pub fn getParamName(mod: *Module, func_index: InternPool.Index, index: u32) [:0]
6169 const tags = file.zir.instructions.items(.tag);6073 const tags = file.zir.instructions.items(.tag);
6170 const data = file.zir.instructions.items(.data);6074 const data = file.zir.instructions.items(.data);
61716075
6172 const param_body = file.zir.getParamBody(func.zir_body_inst);6076 const param_body = file.zir.getParamBody(func.zir_body_inst.resolve(&mod.intern_pool));
6173 const param = param_body[index];6077 const param = param_body[index];
61746078
6175 return switch (tags[@intFromEnum(param)]) {6079 return switch (tags[@intFromEnum(param)]) {
src/Sema.zig+41-29
...@@ -1224,6 +1224,10 @@ fn analyzeBodyInner(...@@ -1224,6 +1224,10 @@ fn analyzeBodyInner(
1224 .trap => break sema.zirTrap(block, inst),1224 .trap => break sema.zirTrap(block, inst),
1225 // zig fmt: on1225 // zig fmt: on
12261226
1227 // This instruction never exists in an analyzed body. It exists only in the declaration
1228 // list for a container type.
1229 .declaration => unreachable,
1230
1227 .extended => ext: {1231 .extended => ext: {
1228 const extended = datas[@intFromEnum(inst)].extended;1232 const extended = datas[@intFromEnum(inst)].extended;
1229 break :ext switch (extended.opcode) {1233 break :ext switch (extended.opcode) {
...@@ -2704,11 +2708,12 @@ pub fn getStructType(...@@ -2704,11 +2708,12 @@ pub fn getStructType(
2704 sema: *Sema,2708 sema: *Sema,
2705 decl: InternPool.DeclIndex,2709 decl: InternPool.DeclIndex,
2706 namespace: InternPool.NamespaceIndex,2710 namespace: InternPool.NamespaceIndex,
2707 zir_index: Zir.Inst.Index,2711 tracked_inst: InternPool.TrackedInst.Index,
2708) !InternPool.Index {2712) !InternPool.Index {
2709 const mod = sema.mod;2713 const mod = sema.mod;
2710 const gpa = sema.gpa;2714 const gpa = sema.gpa;
2711 const ip = &mod.intern_pool;2715 const ip = &mod.intern_pool;
2716 const zir_index = tracked_inst.resolve(ip);
2712 const extended = sema.code.instructions.items(.data)[@intFromEnum(zir_index)].extended;2717 const extended = sema.code.instructions.items(.data)[@intFromEnum(zir_index)].extended;
2713 assert(extended.opcode == .struct_decl);2718 assert(extended.opcode == .struct_decl);
2714 const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small);2719 const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small);
...@@ -2736,12 +2741,14 @@ pub fn getStructType(...@@ -2736,12 +2741,14 @@ pub fn getStructType(
2736 }2741 }
2737 }2742 }
27382743
2739 extra_index = try mod.scanNamespace(namespace, extra_index, decls_len, mod.declPtr(decl));2744 const decls = sema.code.bodySlice(extra_index, decls_len);
2745 try mod.scanNamespace(namespace, decls, mod.declPtr(decl));
2746 extra_index += decls_len;
27402747
2741 const ty = try ip.getStructType(gpa, .{2748 const ty = try ip.getStructType(gpa, .{
2742 .decl = decl,2749 .decl = decl,
2743 .namespace = namespace.toOptional(),2750 .namespace = namespace.toOptional(),
2744 .zir_index = zir_index,2751 .zir_index = tracked_inst,
2745 .layout = small.layout,2752 .layout = small.layout,
2746 .known_non_opv = small.known_non_opv,2753 .known_non_opv = small.known_non_opv,
2747 .is_tuple = small.is_tuple,2754 .is_tuple = small.is_tuple,
...@@ -2791,7 +2798,8 @@ fn zirStructDecl(...@@ -2791,7 +2798,8 @@ fn zirStructDecl(
2791 errdefer mod.destroyNamespace(new_namespace_index);2798 errdefer mod.destroyNamespace(new_namespace_index);
27922799
2793 const struct_ty = ty: {2800 const struct_ty = ty: {
2794 const ty = try sema.getStructType(new_decl_index, new_namespace_index, inst);2801 const tracked_inst = try ip.trackZir(mod.gpa, block.getFileScope(mod), inst);
2802 const ty = try sema.getStructType(new_decl_index, new_namespace_index, tracked_inst);
2795 if (sema.builtin_type_target_index != .none) {2803 if (sema.builtin_type_target_index != .none) {
2796 ip.resolveBuiltinType(sema.builtin_type_target_index, ty);2804 ip.resolveBuiltinType(sema.builtin_type_target_index, ty);
2797 break :ty sema.builtin_type_target_index;2805 break :ty sema.builtin_type_target_index;
...@@ -2850,7 +2858,7 @@ fn createAnonymousDeclTypeNamed(...@@ -2850,7 +2858,7 @@ fn createAnonymousDeclTypeNamed(
2850 return new_decl_index;2858 return new_decl_index;
2851 },2859 },
2852 .func => {2860 .func => {
2853 const fn_info = sema.code.getFnInfo(ip.funcZirBodyInst(sema.func_index));2861 const fn_info = sema.code.getFnInfo(ip.funcZirBodyInst(sema.func_index).resolve(ip));
2854 const zir_tags = sema.code.instructions.items(.tag);2862 const zir_tags = sema.code.instructions.items(.tag);
28552863
2856 var buf = std.ArrayList(u8).init(gpa);2864 var buf = std.ArrayList(u8).init(gpa);
...@@ -2973,7 +2981,9 @@ fn zirEnumDecl(...@@ -2973,7 +2981,9 @@ fn zirEnumDecl(
2973 const new_namespace = mod.namespacePtr(new_namespace_index);2981 const new_namespace = mod.namespacePtr(new_namespace_index);
2974 errdefer if (!done) mod.destroyNamespace(new_namespace_index);2982 errdefer if (!done) mod.destroyNamespace(new_namespace_index);
29752983
2976 extra_index = try mod.scanNamespace(new_namespace_index, extra_index, decls_len, new_decl);2984 const decls = sema.code.bodySlice(extra_index, decls_len);
2985 try mod.scanNamespace(new_namespace_index, decls, new_decl);
2986 extra_index += decls_len;
29772987
2978 const body = sema.code.bodySlice(extra_index, body_len);2988 const body = sema.code.bodySlice(extra_index, body_len);
2979 extra_index += body.len;2989 extra_index += body.len;
...@@ -3244,7 +3254,7 @@ fn zirUnionDecl(...@@ -3244,7 +3254,7 @@ fn zirUnionDecl(
3244 },3254 },
3245 .decl = new_decl_index,3255 .decl = new_decl_index,
3246 .namespace = new_namespace_index,3256 .namespace = new_namespace_index,
3247 .zir_index = inst,3257 .zir_index = try mod.intern_pool.trackZir(gpa, block.getFileScope(mod), inst),
3248 .fields_len = fields_len,3258 .fields_len = fields_len,
3249 .enum_tag_ty = .none,3259 .enum_tag_ty = .none,
3250 .field_types = &.{},3260 .field_types = &.{},
...@@ -3263,7 +3273,8 @@ fn zirUnionDecl(...@@ -3263,7 +3273,8 @@ fn zirUnionDecl(
3263 new_decl.val = Value.fromInterned(union_ty);3273 new_decl.val = Value.fromInterned(union_ty);
3264 new_namespace.ty = Type.fromInterned(union_ty);3274 new_namespace.ty = Type.fromInterned(union_ty);
32653275
3266 _ = try mod.scanNamespace(new_namespace_index, extra_index, decls_len, new_decl);3276 const decls = sema.code.bodySlice(extra_index, decls_len);
3277 try mod.scanNamespace(new_namespace_index, decls, new_decl);
32673278
3268 const decl_val = sema.analyzeDeclVal(block, src, new_decl_index);3279 const decl_val = sema.analyzeDeclVal(block, src, new_decl_index);
3269 try mod.finalizeAnonDecl(new_decl_index);3280 try mod.finalizeAnonDecl(new_decl_index);
...@@ -3326,7 +3337,8 @@ fn zirOpaqueDecl(...@@ -3326,7 +3337,8 @@ fn zirOpaqueDecl(
3326 new_decl.val = Value.fromInterned(opaque_ty);3337 new_decl.val = Value.fromInterned(opaque_ty);
3327 new_namespace.ty = Type.fromInterned(opaque_ty);3338 new_namespace.ty = Type.fromInterned(opaque_ty);
33283339
3329 extra_index = try mod.scanNamespace(new_namespace_index, extra_index, decls_len, new_decl);3340 const decls = sema.code.bodySlice(extra_index, decls_len);
3341 try mod.scanNamespace(new_namespace_index, decls, new_decl);
33303342
3331 const decl_val = sema.analyzeDeclVal(block, src, new_decl_index);3343 const decl_val = sema.analyzeDeclVal(block, src, new_decl_index);
3332 try mod.finalizeAnonDecl(new_decl_index);3344 try mod.finalizeAnonDecl(new_decl_index);
...@@ -7436,7 +7448,7 @@ fn analyzeCall(...@@ -7436,7 +7448,7 @@ fn analyzeCall(
7436 // the AIR instructions of the callsite. The callee could be a generic function7448 // the AIR instructions of the callsite. The callee could be a generic function
7437 // which means its parameter type expressions must be resolved in order and used7449 // which means its parameter type expressions must be resolved in order and used
7438 // to successively coerce the arguments.7450 // to successively coerce the arguments.
7439 const fn_info = ics.callee().code.getFnInfo(module_fn.zir_body_inst);7451 const fn_info = ics.callee().code.getFnInfo(module_fn.zir_body_inst.resolve(ip));
7440 try ics.callee().inst_map.ensureSpaceForInstructions(gpa, fn_info.param_body);7452 try ics.callee().inst_map.ensureSpaceForInstructions(gpa, fn_info.param_body);
74417453
7442 var arg_i: u32 = 0;7454 var arg_i: u32 = 0;
...@@ -7484,7 +7496,7 @@ fn analyzeCall(...@@ -7484,7 +7496,7 @@ fn analyzeCall(
7484 // each of the parameters, resolving the return type and providing it to the child7496 // each of the parameters, resolving the return type and providing it to the child
7485 // `Sema` so that it can be used for the `ret_ptr` instruction.7497 // `Sema` so that it can be used for the `ret_ptr` instruction.
7486 const ret_ty_inst = if (fn_info.ret_ty_body.len != 0)7498 const ret_ty_inst = if (fn_info.ret_ty_body.len != 0)
7487 try sema.resolveBody(&child_block, fn_info.ret_ty_body, module_fn.zir_body_inst)7499 try sema.resolveBody(&child_block, fn_info.ret_ty_body, module_fn.zir_body_inst.resolve(ip))
7488 else7500 else
7489 try sema.resolveInst(fn_info.ret_ty_ref);7501 try sema.resolveInst(fn_info.ret_ty_ref);
7490 const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = 0 };7502 const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = 0 };
...@@ -7875,7 +7887,7 @@ fn instantiateGenericCall(...@@ -7875,7 +7887,7 @@ fn instantiateGenericCall(
7875 const namespace_index = fn_owner_decl.src_namespace;7887 const namespace_index = fn_owner_decl.src_namespace;
7876 const namespace = mod.namespacePtr(namespace_index);7888 const namespace = mod.namespacePtr(namespace_index);
7877 const fn_zir = namespace.file_scope.zir;7889 const fn_zir = namespace.file_scope.zir;
7878 const fn_info = fn_zir.getFnInfo(generic_owner_func.zir_body_inst);7890 const fn_info = fn_zir.getFnInfo(generic_owner_func.zir_body_inst.resolve(ip));
78797891
7880 const comptime_args = try sema.arena.alloc(InternPool.Index, args_info.count());7892 const comptime_args = try sema.arena.alloc(InternPool.Index, args_info.count());
7881 @memset(comptime_args, .none);7893 @memset(comptime_args, .none);
...@@ -9457,7 +9469,7 @@ fn funcCommon(...@@ -9457,7 +9469,7 @@ fn funcCommon(
9457 .is_generic = final_is_generic,9469 .is_generic = final_is_generic,
9458 .is_noinline = is_noinline,9470 .is_noinline = is_noinline,
94599471
9460 .zir_body_inst = func_inst,9472 .zir_body_inst = try ip.trackZir(gpa, block.getFileScope(mod), func_inst),
9461 .lbrace_line = src_locs.lbrace_line,9473 .lbrace_line = src_locs.lbrace_line,
9462 .rbrace_line = src_locs.rbrace_line,9474 .rbrace_line = src_locs.rbrace_line,
9463 .lbrace_column = @as(u16, @truncate(src_locs.columns)),9475 .lbrace_column = @as(u16, @truncate(src_locs.columns)),
...@@ -9535,7 +9547,7 @@ fn funcCommon(...@@ -9535,7 +9547,7 @@ fn funcCommon(
9535 .ty = func_ty,9547 .ty = func_ty,
9536 .cc = cc,9548 .cc = cc,
9537 .is_noinline = is_noinline,9549 .is_noinline = is_noinline,
9538 .zir_body_inst = func_inst,9550 .zir_body_inst = try ip.trackZir(gpa, block.getFileScope(mod), func_inst),
9539 .lbrace_line = src_locs.lbrace_line,9551 .lbrace_line = src_locs.lbrace_line,
9540 .rbrace_line = src_locs.rbrace_line,9552 .rbrace_line = src_locs.rbrace_line,
9541 .lbrace_column = @as(u16, @truncate(src_locs.columns)),9553 .lbrace_column = @as(u16, @truncate(src_locs.columns)),
...@@ -21552,7 +21564,7 @@ fn zirReify(...@@ -21552,7 +21564,7 @@ fn zirReify(
21552 .namespace = new_namespace_index,21564 .namespace = new_namespace_index,
21553 .enum_tag_ty = enum_tag_ty,21565 .enum_tag_ty = enum_tag_ty,
21554 .fields_len = fields_len,21566 .fields_len = fields_len,
21555 .zir_index = inst,21567 .zir_index = try ip.trackZir(gpa, block.getFileScope(mod), inst), // TODO: should reified types be handled differently?
21556 .flags = .{21568 .flags = .{
21557 .layout = layout,21569 .layout = layout,
21558 .status = .have_field_types,21570 .status = .have_field_types,
...@@ -21720,7 +21732,7 @@ fn reifyStruct(...@@ -21720,7 +21732,7 @@ fn reifyStruct(
21720 const ty = try ip.getStructType(gpa, .{21732 const ty = try ip.getStructType(gpa, .{
21721 .decl = new_decl_index,21733 .decl = new_decl_index,
21722 .namespace = .none,21734 .namespace = .none,
21723 .zir_index = inst,21735 .zir_index = try mod.intern_pool.trackZir(gpa, block.getFileScope(mod), inst), // TODO: should reified types be handled differently?
21724 .layout = layout,21736 .layout = layout,
21725 .known_non_opv = false,21737 .known_non_opv = false,
21726 .fields_len = fields_len,21738 .fields_len = fields_len,
...@@ -35592,7 +35604,8 @@ fn semaBackingIntType(mod: *Module, struct_type: InternPool.Key.StructType) Comp...@@ -35592,7 +35604,8 @@ fn semaBackingIntType(mod: *Module, struct_type: InternPool.Key.StructType) Comp
35592 break :blk accumulator;35604 break :blk accumulator;
35593 };35605 };
3559435606
35595 const extended = zir.instructions.items(.data)[@intFromEnum(struct_type.zir_index)].extended;35607 const zir_index = struct_type.zir_index.resolve(ip);
35608 const extended = zir.instructions.items(.data)[@intFromEnum(zir_index)].extended;
35596 assert(extended.opcode == .struct_decl);35609 assert(extended.opcode == .struct_decl);
35597 const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small);35610 const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small);
3559835611
...@@ -35612,7 +35625,7 @@ fn semaBackingIntType(mod: *Module, struct_type: InternPool.Key.StructType) Comp...@@ -35612,7 +35625,7 @@ fn semaBackingIntType(mod: *Module, struct_type: InternPool.Key.StructType) Comp
35612 break :blk try sema.resolveType(&block, backing_int_src, backing_int_ref);35625 break :blk try sema.resolveType(&block, backing_int_src, backing_int_ref);
35613 } else {35626 } else {
35614 const body = zir.bodySlice(extra_index, backing_int_body_len);35627 const body = zir.bodySlice(extra_index, backing_int_body_len);
35615 const ty_ref = try sema.resolveBody(&block, body, struct_type.zir_index);35628 const ty_ref = try sema.resolveBody(&block, body, zir_index);
35616 break :blk try sema.analyzeAsType(&block, backing_int_src, ty_ref);35629 break :blk try sema.analyzeAsType(&block, backing_int_src, ty_ref);
35617 }35630 }
35618 };35631 };
...@@ -36340,9 +36353,7 @@ fn structZirInfo(zir: Zir, zir_index: Zir.Inst.Index) struct {...@@ -36340,9 +36353,7 @@ fn structZirInfo(zir: Zir, zir_index: Zir.Inst.Index) struct {
36340 }36353 }
3634136354
36342 // Skip over decls.36355 // Skip over decls.
36343 var decls_it = zir.declIteratorInner(extra_index, decls_len);36356 extra_index += decls_len;
36344 while (decls_it.next()) |_| {}
36345 extra_index = decls_it.extra_index;
3634636357
36347 return .{ fields_len, small, extra_index };36358 return .{ fields_len, small, extra_index };
36348}36359}
...@@ -36358,7 +36369,7 @@ fn semaStructFields(...@@ -36358,7 +36369,7 @@ fn semaStructFields(
36358 const decl = mod.declPtr(decl_index);36369 const decl = mod.declPtr(decl_index);
36359 const namespace_index = struct_type.namespace.unwrap() orelse decl.src_namespace;36370 const namespace_index = struct_type.namespace.unwrap() orelse decl.src_namespace;
36360 const zir = mod.namespacePtr(namespace_index).file_scope.zir;36371 const zir = mod.namespacePtr(namespace_index).file_scope.zir;
36361 const zir_index = struct_type.zir_index;36372 const zir_index = struct_type.zir_index.resolve(ip);
3636236373
36363 const fields_len, const small, var extra_index = structZirInfo(zir, zir_index);36374 const fields_len, const small, var extra_index = structZirInfo(zir, zir_index);
3636436375
...@@ -36629,7 +36640,7 @@ fn semaStructFieldInits(...@@ -36629,7 +36640,7 @@ fn semaStructFieldInits(
36629 const decl = mod.declPtr(decl_index);36640 const decl = mod.declPtr(decl_index);
36630 const namespace_index = struct_type.namespace.unwrap() orelse decl.src_namespace;36641 const namespace_index = struct_type.namespace.unwrap() orelse decl.src_namespace;
36631 const zir = mod.namespacePtr(namespace_index).file_scope.zir;36642 const zir = mod.namespacePtr(namespace_index).file_scope.zir;
36632 const zir_index = struct_type.zir_index;36643 const zir_index = struct_type.zir_index.resolve(ip);
36633 const fields_len, const small, var extra_index = structZirInfo(zir, zir_index);36644 const fields_len, const small, var extra_index = structZirInfo(zir, zir_index);
3663436645
36635 var comptime_mutable_decls = std.ArrayList(InternPool.DeclIndex).init(gpa);36646 var comptime_mutable_decls = std.ArrayList(InternPool.DeclIndex).init(gpa);
...@@ -36778,7 +36789,8 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Key.Un...@@ -36778,7 +36789,8 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Key.Un
36778 const ip = &mod.intern_pool;36789 const ip = &mod.intern_pool;
36779 const decl_index = union_type.decl;36790 const decl_index = union_type.decl;
36780 const zir = mod.namespacePtr(union_type.namespace).file_scope.zir;36791 const zir = mod.namespacePtr(union_type.namespace).file_scope.zir;
36781 const extended = zir.instructions.items(.data)[@intFromEnum(union_type.zir_index)].extended;36792 const zir_index = union_type.zir_index.resolve(ip);
36793 const extended = zir.instructions.items(.data)[@intFromEnum(zir_index)].extended;
36782 assert(extended.opcode == .union_decl);36794 assert(extended.opcode == .union_decl);
36783 const small: Zir.Inst.UnionDecl.Small = @bitCast(extended.small);36795 const small: Zir.Inst.UnionDecl.Small = @bitCast(extended.small);
36784 var extra_index: usize = extended.operand;36796 var extra_index: usize = extended.operand;
...@@ -36811,9 +36823,7 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Key.Un...@@ -36811,9 +36823,7 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Key.Un
36811 } else 0;36823 } else 0;
3681236824
36813 // Skip over decls.36825 // Skip over decls.
36814 var decls_it = zir.declIteratorInner(extra_index, decls_len);36826 extra_index += decls_len;
36815 while (decls_it.next()) |_| {}
36816 extra_index = decls_it.extra_index;
3681736827
36818 const body = zir.bodySlice(extra_index, body_len);36828 const body = zir.bodySlice(extra_index, body_len);
36819 extra_index += body.len;36829 extra_index += body.len;
...@@ -37810,10 +37820,12 @@ pub fn analyzeAddressSpace(...@@ -37810,10 +37820,12 @@ pub fn analyzeAddressSpace(
37810 ctx: AddressSpaceContext,37820 ctx: AddressSpaceContext,
37811) !std.builtin.AddressSpace {37821) !std.builtin.AddressSpace {
37812 const mod = sema.mod;37822 const mod = sema.mod;
37813 const addrspace_tv = try sema.resolveInstConst(block, src, zir_ref, .{37823 const air_ref = try sema.resolveInst(zir_ref);
37824 const coerced = try sema.coerce(block, Type.fromInterned(.address_space_type), air_ref, src);
37825 const addrspace_val = try sema.resolveConstDefinedValue(block, src, coerced, .{
37814 .needed_comptime_reason = "address space must be comptime-known",37826 .needed_comptime_reason = "address space must be comptime-known",
37815 });37827 });
37816 const address_space = mod.toEnum(std.builtin.AddressSpace, addrspace_tv.val);37828 const address_space = mod.toEnum(std.builtin.AddressSpace, addrspace_val);
37817 const target = sema.mod.getTarget();37829 const target = sema.mod.getTarget();
37818 const arch = target.cpu.arch;37830 const arch = target.cpu.arch;
3781937831
src/Zir.zig+213-187
...@@ -30,7 +30,7 @@ instructions: std.MultiArrayList(Inst).Slice,...@@ -30,7 +30,7 @@ instructions: std.MultiArrayList(Inst).Slice,
30/// is referencing the data here whether they want to store both index and length,30/// is referencing the data here whether they want to store both index and length,
31/// thus allowing null bytes, or store only index, and use null-termination. The31/// thus allowing null bytes, or store only index, and use null-termination. The
32/// `string_bytes` array is agnostic to either usage.32/// `string_bytes` array is agnostic to either usage.
33/// Indexes 0 and 1 are reserved for special cases.33/// Index 0 is reserved for special cases.
34string_bytes: []u8,34string_bytes: []u8,
35/// The meaning of this data is determined by `Inst.Tag` value.35/// The meaning of this data is determined by `Inst.Tag` value.
36/// The first few indexes are reserved. See `ExtraIndex` for the values.36/// The first few indexes are reserved. See `ExtraIndex` for the values.
...@@ -60,21 +60,6 @@ pub const ExtraIndex = enum(u32) {...@@ -60,21 +60,6 @@ pub const ExtraIndex = enum(u32) {
60 imports,60 imports,
6161
62 _,62 _,
63
64 pub fn toOptional(i: ExtraIndex) OptionalExtraIndex {
65 return @enumFromInt(@intFromEnum(i));
66 }
67};
68
69pub const OptionalExtraIndex = enum(u32) {
70 compile_errors,
71 imports,
72 none = std.math.maxInt(u32),
73 _,
74
75 pub fn unwrap(oi: OptionalExtraIndex) ?ExtraIndex {
76 return if (oi == .none) null else @enumFromInt(@intFromEnum(oi));
77 }
78};63};
7964
80fn ExtraData(comptime T: type) type {65fn ExtraData(comptime T: type) type {
...@@ -93,6 +78,7 @@ pub fn extraData(code: Zir, comptime T: type, index: usize) ExtraData(T) {...@@ -93,6 +78,7 @@ pub fn extraData(code: Zir, comptime T: type, index: usize) ExtraData(T) {
9378
94 Inst.Ref,79 Inst.Ref,
95 Inst.Index,80 Inst.Index,
81 Inst.Declaration.Name,
96 NullTerminatedString,82 NullTerminatedString,
97 => @enumFromInt(code.extra[i]),83 => @enumFromInt(code.extra[i]),
9884
...@@ -102,6 +88,7 @@ pub fn extraData(code: Zir, comptime T: type, index: usize) ExtraData(T) {...@@ -102,6 +88,7 @@ pub fn extraData(code: Zir, comptime T: type, index: usize) ExtraData(T) {
102 Inst.SwitchBlock.Bits,88 Inst.SwitchBlock.Bits,
103 Inst.SwitchBlockErrUnion.Bits,89 Inst.SwitchBlockErrUnion.Bits,
104 Inst.FuncFancy.Bits,90 Inst.FuncFancy.Bits,
91 Inst.Declaration.Flags,
105 => @bitCast(code.extra[i]),92 => @bitCast(code.extra[i]),
10693
107 else => @compileError("bad field type"),94 else => @compileError("bad field type"),
...@@ -116,8 +103,6 @@ pub fn extraData(code: Zir, comptime T: type, index: usize) ExtraData(T) {...@@ -116,8 +103,6 @@ pub fn extraData(code: Zir, comptime T: type, index: usize) ExtraData(T) {
116103
117pub const NullTerminatedString = enum(u32) {104pub const NullTerminatedString = enum(u32) {
118 empty = 0,105 empty = 0,
119 unnamed_test_decl = 1,
120 decltest = 2,
121 _,106 _,
122};107};
123108
...@@ -304,6 +289,12 @@ pub const Inst = struct {...@@ -304,6 +289,12 @@ pub const Inst = struct {
304 /// a noreturn instruction.289 /// a noreturn instruction.
305 /// Uses the `pl_node` union field. Payload is `Block`.290 /// Uses the `pl_node` union field. Payload is `Block`.
306 block_inline,291 block_inline,
292 /// This instruction may only ever appear in the list of declarations for a
293 /// namespace type, e.g. within a `struct_decl` instruction. It represents a
294 /// single source declaration (`const`/`var`/`fn`), containing the name,
295 /// attributes, type, and value of the declaration.
296 /// Uses the `pl_node` union field. Payload is `Declaration`.
297 declaration,
307 /// Implements `suspend {...}`.298 /// Implements `suspend {...}`.
308 /// Uses the `pl_node` union field. Payload is `Block`.299 /// Uses the `pl_node` union field. Payload is `Block`.
309 suspend_block,300 suspend_block,
...@@ -1092,6 +1083,7 @@ pub const Inst = struct {...@@ -1092,6 +1083,7 @@ pub const Inst = struct {
1092 .block,1083 .block,
1093 .block_comptime,1084 .block_comptime,
1094 .block_inline,1085 .block_inline,
1086 .declaration,
1095 .suspend_block,1087 .suspend_block,
1096 .loop,1088 .loop,
1097 .bool_br_and,1089 .bool_br_and,
...@@ -1405,6 +1397,7 @@ pub const Inst = struct {...@@ -1405,6 +1397,7 @@ pub const Inst = struct {
1405 .block,1397 .block,
1406 .block_comptime,1398 .block_comptime,
1407 .block_inline,1399 .block_inline,
1400 .declaration,
1408 .suspend_block,1401 .suspend_block,
1409 .loop,1402 .loop,
1410 .bool_br_and,1403 .bool_br_and,
...@@ -1639,6 +1632,7 @@ pub const Inst = struct {...@@ -1639,6 +1632,7 @@ pub const Inst = struct {
1639 .block = .pl_node,1632 .block = .pl_node,
1640 .block_comptime = .pl_node,1633 .block_comptime = .pl_node,
1641 .block_inline = .pl_node,1634 .block_inline = .pl_node,
1635 .declaration = .pl_node,
1642 .suspend_block = .pl_node,1636 .suspend_block = .pl_node,
1643 .bool_not = .un_node,1637 .bool_not = .un_node,
1644 .bool_br_and = .bool_br,1638 .bool_br_and = .bool_br,
...@@ -2508,6 +2502,7 @@ pub const Inst = struct {...@@ -2508,6 +2502,7 @@ pub const Inst = struct {
2508 /// If this is 1 it means return_type is a simple Ref2502 /// If this is 1 it means return_type is a simple Ref
2509 ret_body_len: u32,2503 ret_body_len: u32,
2510 /// Points to the block that contains the param instructions for this function.2504 /// Points to the block that contains the param instructions for this function.
2505 /// If this is a `declaration`, it refers to the declaration's value body.
2511 param_block: Index,2506 param_block: Index,
2512 body_len: u32,2507 body_len: u32,
25132508
...@@ -2565,6 +2560,7 @@ pub const Inst = struct {...@@ -2565,6 +2560,7 @@ pub const Inst = struct {
2565 /// 18. src_locs: Func.SrcLocs // if body_len != 02560 /// 18. src_locs: Func.SrcLocs // if body_len != 0
2566 pub const FuncFancy = struct {2561 pub const FuncFancy = struct {
2567 /// Points to the block that contains the param instructions for this function.2562 /// 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.
2568 param_block: Index,2564 param_block: Index,
2569 body_len: u32,2565 body_len: u32,
2570 bits: Bits,2566 bits: Bits,
...@@ -2632,6 +2628,116 @@ pub const Inst = struct {...@@ -2632,6 +2628,116 @@ pub const Inst = struct {
2632 body_len: u32,2628 body_len: u32,
2633 };2629 };
26342630
2631 /// Trailing:
2632 /// 0. doc_comment: u32 // if `has_doc_comment`; null-terminated string index
2633 /// 1. align_body_len: u32 // if `has_align_linksection_addrspace`; 0 means no `align`
2634 /// 2. linksection_body_len: u32 // if `has_align_linksection_addrspace`; 0 means no `linksection`
2635 /// 3. addrspace_body_len: u32 // if `has_align_linksection_addrspace`; 0 means no `addrspace`
2636 /// 4. value_body_inst: Zir.Inst.Index
2637 /// - for each `value_body_len`
2638 /// - body to be exited via `break_inline` to this `declaration` instruction
2639 /// 5. align_body_inst: Zir.Inst.Index
2640 /// - for each `align_body_len`
2641 /// - body to be exited via `break_inline` to this `declaration` instruction
2642 /// 6. linksection_body_inst: Zir.Inst.Index
2643 /// - for each `linksection_body_len`
2644 /// - body to be exited via `break_inline` to this `declaration` instruction
2645 /// 7. addrspace_body_inst: Zir.Inst.Index
2646 /// - for each `addrspace_body_len`
2647 /// - body to be exited via `break_inline` to this `declaration` instruction
2648 pub const Declaration = struct {
2649 // These fields should be concatenated and reinterpreted as a `std.zig.SrcHash`.
2650 src_hash_0: u32,
2651 src_hash_1: u32,
2652 src_hash_2: u32,
2653 src_hash_3: u32,
2654 /// The name of this `Decl`. Also indicates whether it is a test, comptime block, etc.
2655 name: Name,
2656 /// This Decl's line number relative to that of its parent.
2657 /// TODO: column must be encoded similarly to respect non-formatted code!
2658 line_offset: u32,
2659 flags: Flags,
2660
2661 pub const Flags = packed struct(u32) {
2662 value_body_len: u28,
2663 is_pub: bool,
2664 is_export: bool,
2665 has_doc_comment: bool,
2666 has_align_linksection_addrspace: bool,
2667 };
2668
2669 pub const Name = enum(u32) {
2670 @"comptime" = std.math.maxInt(u32),
2671 @"usingnamespace" = std.math.maxInt(u32) - 1,
2672 unnamed_test = std.math.maxInt(u32) - 2,
2673 /// In this case, `has_doc_comment` will be true, and the doc
2674 /// comment body is the identifier name.
2675 decltest = std.math.maxInt(u32) - 3,
2676 /// Other values are `NullTerminatedString` values, i.e. index into
2677 /// `string_bytes`. If the byte referenced is 0, the decl is a named
2678 /// test, and the actual name begins at the following byte.
2679 _,
2680
2681 pub fn isNamedTest(name: Name, zir: Zir) bool {
2682 return switch (name) {
2683 .@"comptime", .@"usingnamespace", .unnamed_test, .decltest => false,
2684 _ => zir.string_bytes[@intFromEnum(name)] == 0,
2685 };
2686 }
2687 pub fn toString(name: Name, zir: Zir) ?NullTerminatedString {
2688 switch (name) {
2689 .@"comptime", .@"usingnamespace", .unnamed_test, .decltest => return null,
2690 _ => {},
2691 }
2692 const idx: u32 = @intFromEnum(name);
2693 if (zir.string_bytes[idx] == 0) {
2694 // Named test
2695 return @enumFromInt(idx + 1);
2696 }
2697 return @enumFromInt(idx);
2698 }
2699 };
2700
2701 pub const Bodies = struct {
2702 value_body: []const Index,
2703 align_body: ?[]const Index,
2704 linksection_body: ?[]const Index,
2705 addrspace_body: ?[]const Index,
2706 };
2707
2708 pub fn getBodies(declaration: Declaration, extra_end: u32, zir: Zir) Bodies {
2709 var extra_index: u32 = extra_end;
2710 extra_index += @intFromBool(declaration.flags.has_doc_comment);
2711 const value_body_len = declaration.flags.value_body_len;
2712 const align_body_len, const linksection_body_len, const addrspace_body_len = lens: {
2713 if (!declaration.flags.has_align_linksection_addrspace) {
2714 break :lens .{ 0, 0, 0 };
2715 }
2716 const lens = zir.extra[extra_index..][0..3].*;
2717 extra_index += 3;
2718 break :lens lens;
2719 };
2720 return .{
2721 .value_body = b: {
2722 defer extra_index += value_body_len;
2723 break :b zir.bodySlice(extra_index, value_body_len);
2724 },
2725 .align_body = if (align_body_len == 0) null else b: {
2726 defer extra_index += align_body_len;
2727 break :b zir.bodySlice(extra_index, align_body_len);
2728 },
2729 .linksection_body = if (linksection_body_len == 0) null else b: {
2730 defer extra_index += linksection_body_len;
2731 break :b zir.bodySlice(extra_index, linksection_body_len);
2732 },
2733 .addrspace_body = if (addrspace_body_len == 0) null else b: {
2734 defer extra_index += addrspace_body_len;
2735 break :b zir.bodySlice(extra_index, addrspace_body_len);
2736 },
2737 };
2738 }
2739 };
2740
2635 /// Stored inside extra, with trailing arguments according to `args_len`.2741 /// Stored inside extra, with trailing arguments according to `args_len`.
2636 /// Implicit 0. arg_0_start: u32, // always same as `args_len`2742 /// Implicit 0. arg_0_start: u32, // always same as `args_len`
2637 /// 1. arg_end: u32, // for each `args_len`2743 /// 1. arg_end: u32, // for each `args_len`
...@@ -2913,37 +3019,14 @@ pub const Inst = struct {...@@ -2913,37 +3019,14 @@ pub const Inst = struct {
2913 /// 3. backing_int_body_len: u32, // if has_backing_int3019 /// 3. backing_int_body_len: u32, // if has_backing_int
2914 /// 4. backing_int_ref: Ref, // if has_backing_int and backing_int_body_len is 03020 /// 4. backing_int_ref: Ref, // if has_backing_int and backing_int_body_len is 0
2915 /// 5. backing_int_body_inst: Inst, // if has_backing_int and backing_int_body_len is > 03021 /// 5. backing_int_body_inst: Inst, // if has_backing_int and backing_int_body_len is > 0
2916 /// 6. decl_bits: u32 // for every 8 decls3022 /// 6. decl: Index, // for every decls_len; points to a `declaration` instruction
2917 /// - sets of 4 bits:3023 /// 7. flags: u32 // for every 8 fields
2918 /// 0b000X: whether corresponding decl is pub
2919 /// 0b00X0: whether corresponding decl is exported
2920 /// 0b0X00: whether corresponding decl has an align expression
2921 /// 0bX000: whether corresponding decl has a linksection or an address space expression
2922 /// 7. decl: { // for every decls_len
2923 /// src_hash: [4]u32, // hash of source bytes
2924 /// line: u32, // line number of decl, relative to parent
2925 /// name: NullTerminatedString, // null terminated string index
2926 /// - 0 means comptime or usingnamespace decl.
2927 /// - if name == 0 `is_exported` determines which one: 0=comptime,1=usingnamespace
2928 /// - 1 means test decl with no name.
2929 /// - 2 means that the test is a decltest, doc_comment gives the name of the identifier
2930 /// - if there is a 0 byte at the position `name` indexes, it indicates
2931 /// this is a test decl, and the name starts at `name+1`.
2932 /// value: Index,
2933 /// doc_comment: u32, .empty if no doc comment, if this is a decltest, doc_comment references the decl name in the string table
2934 /// align: Ref, // if corresponding bit is set
2935 /// link_section_or_address_space: { // if corresponding bit is set.
2936 /// link_section: Ref,
2937 /// address_space: Ref,
2938 /// }
2939 /// }
2940 /// 8. flags: u32 // for every 8 fields
2941 /// - sets of 4 bits:3024 /// - sets of 4 bits:
2942 /// 0b000X: whether corresponding field has an align expression3025 /// 0b000X: whether corresponding field has an align expression
2943 /// 0b00X0: whether corresponding field has a default expression3026 /// 0b00X0: whether corresponding field has a default expression
2944 /// 0b0X00: whether corresponding field is comptime3027 /// 0b0X00: whether corresponding field is comptime
2945 /// 0bX000: whether corresponding field has a type expression3028 /// 0bX000: whether corresponding field has a type expression
2946 /// 9. fields: { // for every fields_len3029 /// 8. fields: { // for every fields_len
2947 /// field_name: u32, // if !is_tuple3030 /// field_name: u32, // if !is_tuple
2948 /// doc_comment: NullTerminatedString, // .empty if no doc comment3031 /// doc_comment: NullTerminatedString, // .empty if no doc comment
2949 /// field_type: Ref, // if corresponding bit is not set. none means anytype.3032 /// field_type: Ref, // if corresponding bit is not set. none means anytype.
...@@ -3009,33 +3092,11 @@ pub const Inst = struct {...@@ -3009,33 +3092,11 @@ pub const Inst = struct {
3009 /// 2. body_len: u32, // if has_body_len3092 /// 2. body_len: u32, // if has_body_len
3010 /// 3. fields_len: u32, // if has_fields_len3093 /// 3. fields_len: u32, // if has_fields_len
3011 /// 4. decls_len: u32, // if has_decls_len3094 /// 4. decls_len: u32, // if has_decls_len
3012 /// 5. decl_bits: u32 // for every 8 decls3095 /// 5. decl: Index, // for every decls_len; points to a `declaration` instruction
3013 /// - sets of 4 bits:3096 /// 6. inst: Index // for every body_len
3014 /// 0b000X: whether corresponding decl is pub3097 /// 7. has_bits: u32 // for every 32 fields
3015 /// 0b00X0: whether corresponding decl is exported
3016 /// 0b0X00: whether corresponding decl has an align expression
3017 /// 0bX000: whether corresponding decl has a linksection or an address space expression
3018 /// 6. decl: { // for every decls_len
3019 /// src_hash: [4]u32, // hash of source bytes
3020 /// line: u32, // line number of decl, relative to parent
3021 /// name: NullTerminatedString, // null terminated string index
3022 /// - 0 means comptime or usingnamespace decl.
3023 /// - if name == 0 `is_exported` determines which one: 0=comptime,1=usingnamespace
3024 /// - 1 means test decl with no name.
3025 /// - if there is a 0 byte at the position `name` indexes, it indicates
3026 /// this is a test decl, and the name starts at `name+1`.
3027 /// value: Index,
3028 /// doc_comment: u32, // .empty if no doc_comment
3029 /// align: Ref, // if corresponding bit is set
3030 /// link_section_or_address_space: { // if corresponding bit is set.
3031 /// link_section: Ref,
3032 /// address_space: Ref,
3033 /// }
3034 /// }
3035 /// 7. inst: Index // for every body_len
3036 /// 8. has_bits: u32 // for every 32 fields
3037 /// - the bit is whether corresponding field has an value expression3098 /// - the bit is whether corresponding field has an value expression
3038 /// 9. fields: { // for every fields_len3099 /// 8. fields: { // for every fields_len
3039 /// field_name: u32,3100 /// field_name: u32,
3040 /// doc_comment: u32, // .empty if no doc_comment3101 /// doc_comment: u32, // .empty if no doc_comment
3041 /// value: Ref, // if corresponding bit is set3102 /// value: Ref, // if corresponding bit is set
...@@ -3059,37 +3120,15 @@ pub const Inst = struct {...@@ -3059,37 +3120,15 @@ pub const Inst = struct {
3059 /// 2. body_len: u32, // if has_body_len3120 /// 2. body_len: u32, // if has_body_len
3060 /// 3. fields_len: u32, // if has_fields_len3121 /// 3. fields_len: u32, // if has_fields_len
3061 /// 4. decls_len: u32, // if has_decls_len3122 /// 4. decls_len: u32, // if has_decls_len
3062 /// 5. decl_bits: u32 // for every 8 decls3123 /// 5. decl: Index, // for every decls_len; points to a `declaration` instruction
3063 /// - sets of 4 bits:3124 /// 6. inst: Index // for every body_len
3064 /// 0b000X: whether corresponding decl is pub3125 /// 7. has_bits: u32 // for every 8 fields
3065 /// 0b00X0: whether corresponding decl is exported
3066 /// 0b0X00: whether corresponding decl has an align expression
3067 /// 0bX000: whether corresponding decl has a linksection or an address space expression
3068 /// 6. decl: { // for every decls_len
3069 /// src_hash: [4]u32, // hash of source bytes
3070 /// line: u32, // line number of decl, relative to parent
3071 /// name: NullTerminatedString, // null terminated string index
3072 /// - 0 means comptime or usingnamespace decl.
3073 /// - if name == 0 `is_exported` determines which one: 0=comptime,1=usingnamespace
3074 /// - 1 means test decl with no name.
3075 /// - if there is a 0 byte at the position `name` indexes, it indicates
3076 /// this is a test decl, and the name starts at `name+1`.
3077 /// value: Index,
3078 /// doc_comment: NullTerminatedString, // .empty if no doc comment
3079 /// align: Ref, // if corresponding bit is set
3080 /// link_section_or_address_space: { // if corresponding bit is set.
3081 /// link_section: Ref,
3082 /// address_space: Ref,
3083 /// }
3084 /// }
3085 /// 7. inst: Index // for every body_len
3086 /// 8. has_bits: u32 // for every 8 fields
3087 /// - sets of 4 bits:3126 /// - sets of 4 bits:
3088 /// 0b000X: whether corresponding field has a type expression3127 /// 0b000X: whether corresponding field has a type expression
3089 /// 0b00X0: whether corresponding field has a align expression3128 /// 0b00X0: whether corresponding field has a align expression
3090 /// 0b0X00: whether corresponding field has a tag value expression3129 /// 0b0X00: whether corresponding field has a tag value expression
3091 /// 0bX000: unused3130 /// 0bX000: unused
3092 /// 9. fields: { // for every fields_len3131 /// 8. fields: { // for every fields_len
3093 /// field_name: NullTerminatedString, // null terminated string index3132 /// field_name: NullTerminatedString, // null terminated string index
3094 /// doc_comment: NullTerminatedString, // .empty if no doc comment3133 /// doc_comment: NullTerminatedString, // .empty if no doc comment
3095 /// field_type: Ref, // if corresponding bit is set3134 /// field_type: Ref, // if corresponding bit is set
...@@ -3121,29 +3160,7 @@ pub const Inst = struct {...@@ -3121,29 +3160,7 @@ pub const Inst = struct {
3121 /// Trailing:3160 /// Trailing:
3122 /// 0. src_node: i32, // if has_src_node3161 /// 0. src_node: i32, // if has_src_node
3123 /// 1. decls_len: u32, // if has_decls_len3162 /// 1. decls_len: u32, // if has_decls_len
3124 /// 2. decl_bits: u32 // for every 8 decls3163 /// 2. decl: Index, // for every decls_len; points to a `declaration` instruction
3125 /// - sets of 4 bits:
3126 /// 0b000X: whether corresponding decl is pub
3127 /// 0b00X0: whether corresponding decl is exported
3128 /// 0b0X00: whether corresponding decl has an align expression
3129 /// 0bX000: whether corresponding decl has a linksection or an address space expression
3130 /// 3. decl: { // for every decls_len
3131 /// src_hash: [4]u32, // hash of source bytes
3132 /// line: u32, // line number of decl, relative to parent
3133 /// name: NullTerminatedString, // null terminated string index
3134 /// - 0 means comptime or usingnamespace decl.
3135 /// - if name == 0 `is_exported` determines which one: 0=comptime,1=usingnamespace
3136 /// - 1 means test decl with no name.
3137 /// - if there is a 0 byte at the position `name` indexes, it indicates
3138 /// this is a test decl, and the name starts at `name+1`.
3139 /// value: Index,
3140 /// doc_comment: NullTerminatedString, // .empty if no doc comment,
3141 /// align: Ref, // if corresponding bit is set
3142 /// link_section_or_address_space: { // if corresponding bit is set.
3143 /// link_section: Ref,
3144 /// address_space: Ref,
3145 /// }
3146 /// }
3147 pub const OpaqueDecl = struct {3164 pub const OpaqueDecl = struct {
3148 pub const Small = packed struct {3165 pub const Small = packed struct {
3149 has_src_node: bool,3166 has_src_node: bool,
...@@ -3407,44 +3424,17 @@ pub const Inst = struct {...@@ -3407,44 +3424,17 @@ pub const Inst = struct {
3407pub const SpecialProng = enum { none, @"else", under };3424pub const SpecialProng = enum { none, @"else", under };
34083425
3409pub const DeclIterator = struct {3426pub const DeclIterator = struct {
3410 extra_index: usize,3427 extra_index: u32,
3411 bit_bag_index: usize,3428 decls_remaining: u32,
3412 cur_bit_bag: u32,
3413 decl_i: u32,
3414 decls_len: u32,
3415 zir: Zir,3429 zir: Zir,
34163430
3417 pub const Item = struct {3431 pub fn next(it: *DeclIterator) ?Inst.Index {
3418 name: [:0]const u8,3432 if (it.decls_remaining == 0) return null;
3419 sub_index: ExtraIndex,3433 const decl_inst: Zir.Inst.Index = @enumFromInt(it.zir.extra[it.extra_index]);
3420 flags: u4,3434 it.extra_index += 1;
3421 };3435 it.decls_remaining -= 1;
34223436 assert(it.zir.instructions.items(.tag)[@intFromEnum(decl_inst)] == .declaration);
3423 pub fn next(it: *DeclIterator) ?Item {3437 return decl_inst;
3424 if (it.decl_i >= it.decls_len) return null;
3425
3426 if (it.decl_i % 8 == 0) {
3427 it.cur_bit_bag = it.zir.extra[it.bit_bag_index];
3428 it.bit_bag_index += 1;
3429 }
3430 it.decl_i += 1;
3431
3432 const flags: u4 = @truncate(it.cur_bit_bag);
3433 it.cur_bit_bag >>= 4;
3434
3435 const sub_index: ExtraIndex = @enumFromInt(it.extra_index);
3436 it.extra_index += 5; // src_hash(4) + line(1)
3437 const name = it.zir.nullTerminatedString(@enumFromInt(it.zir.extra[it.extra_index]));
3438 it.extra_index += 3; // name(1) + value(1) + doc_comment(1)
3439 it.extra_index += @as(u1, @truncate(flags >> 2)); // align
3440 it.extra_index += @as(u1, @truncate(flags >> 3)); // link_section
3441 it.extra_index += @as(u1, @truncate(flags >> 3)); // address_space
3442
3443 return Item{
3444 .sub_index = sub_index,
3445 .name = name,
3446 .flags = flags,
3447 };
3448 }3438 }
3449};3439};
34503440
...@@ -3454,14 +3444,18 @@ pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator {...@@ -3454,14 +3444,18 @@ pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator {
3454 switch (tags[@intFromEnum(decl_inst)]) {3444 switch (tags[@intFromEnum(decl_inst)]) {
3455 // Functions are allowed and yield no iterations.3445 // Functions are allowed and yield no iterations.
3456 // There is one case matching this in the extended instruction set below.3446 // There is one case matching this in the extended instruction set below.
3457 .func, .func_inferred, .func_fancy => return declIteratorInner(zir, 0, 0),3447 .func, .func_inferred, .func_fancy => return .{
3448 .extra_index = undefined,
3449 .decls_remaining = 0,
3450 .zir = zir,
3451 },
34583452
3459 .extended => {3453 .extended => {
3460 const extended = datas[@intFromEnum(decl_inst)].extended;3454 const extended = datas[@intFromEnum(decl_inst)].extended;
3461 switch (extended.opcode) {3455 switch (extended.opcode) {
3462 .struct_decl => {3456 .struct_decl => {
3463 const small: Inst.StructDecl.Small = @bitCast(extended.small);3457 const small: Inst.StructDecl.Small = @bitCast(extended.small);
3464 var extra_index: usize = extended.operand;3458 var extra_index: u32 = extended.operand;
3465 extra_index += @intFromBool(small.has_src_node);3459 extra_index += @intFromBool(small.has_src_node);
3466 extra_index += @intFromBool(small.has_fields_len);3460 extra_index += @intFromBool(small.has_fields_len);
3467 const decls_len = if (small.has_decls_len) decls_len: {3461 const decls_len = if (small.has_decls_len) decls_len: {
...@@ -3480,11 +3474,15 @@ pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator {...@@ -3480,11 +3474,15 @@ pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator {
3480 }3474 }
3481 }3475 }
34823476
3483 return declIteratorInner(zir, extra_index, decls_len);3477 return .{
3478 .extra_index = extra_index,
3479 .decls_remaining = decls_len,
3480 .zir = zir,
3481 };
3484 },3482 },
3485 .enum_decl => {3483 .enum_decl => {
3486 const small: Inst.EnumDecl.Small = @bitCast(extended.small);3484 const small: Inst.EnumDecl.Small = @bitCast(extended.small);
3487 var extra_index: usize = extended.operand;3485 var extra_index: u32 = extended.operand;
3488 extra_index += @intFromBool(small.has_src_node);3486 extra_index += @intFromBool(small.has_src_node);
3489 extra_index += @intFromBool(small.has_tag_type);3487 extra_index += @intFromBool(small.has_tag_type);
3490 extra_index += @intFromBool(small.has_body_len);3488 extra_index += @intFromBool(small.has_body_len);
...@@ -3495,11 +3493,15 @@ pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator {...@@ -3495,11 +3493,15 @@ pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator {
3495 break :decls_len decls_len;3493 break :decls_len decls_len;
3496 } else 0;3494 } else 0;
34973495
3498 return declIteratorInner(zir, extra_index, decls_len);3496 return .{
3497 .extra_index = extra_index,
3498 .decls_remaining = decls_len,
3499 .zir = zir,
3500 };
3499 },3501 },
3500 .union_decl => {3502 .union_decl => {
3501 const small: Inst.UnionDecl.Small = @bitCast(extended.small);3503 const small: Inst.UnionDecl.Small = @bitCast(extended.small);
3502 var extra_index: usize = extended.operand;3504 var extra_index: u32 = extended.operand;
3503 extra_index += @intFromBool(small.has_src_node);3505 extra_index += @intFromBool(small.has_src_node);
3504 extra_index += @intFromBool(small.has_tag_type);3506 extra_index += @intFromBool(small.has_tag_type);
3505 extra_index += @intFromBool(small.has_body_len);3507 extra_index += @intFromBool(small.has_body_len);
...@@ -3510,11 +3512,15 @@ pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator {...@@ -3510,11 +3512,15 @@ pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator {
3510 break :decls_len decls_len;3512 break :decls_len decls_len;
3511 } else 0;3513 } else 0;
35123514
3513 return declIteratorInner(zir, extra_index, decls_len);3515 return .{
3516 .extra_index = extra_index,
3517 .decls_remaining = decls_len,
3518 .zir = zir,
3519 };
3514 },3520 },
3515 .opaque_decl => {3521 .opaque_decl => {
3516 const small: Inst.OpaqueDecl.Small = @bitCast(extended.small);3522 const small: Inst.OpaqueDecl.Small = @bitCast(extended.small);
3517 var extra_index: usize = extended.operand;3523 var extra_index: u32 = extended.operand;
3518 extra_index += @intFromBool(small.has_src_node);3524 extra_index += @intFromBool(small.has_src_node);
3519 const decls_len = if (small.has_decls_len) decls_len: {3525 const decls_len = if (small.has_decls_len) decls_len: {
3520 const decls_len = zir.extra[extra_index];3526 const decls_len = zir.extra[extra_index];
...@@ -3522,7 +3528,11 @@ pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator {...@@ -3522,7 +3528,11 @@ pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator {
3522 break :decls_len decls_len;3528 break :decls_len decls_len;
3523 } else 0;3529 } else 0;
35243530
3525 return declIteratorInner(zir, extra_index, decls_len);3531 return .{
3532 .extra_index = extra_index,
3533 .decls_remaining = decls_len,
3534 .zir = zir,
3535 };
3526 },3536 },
3527 else => unreachable,3537 else => unreachable,
3528 }3538 }
...@@ -3531,25 +3541,17 @@ pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator {...@@ -3531,25 +3541,17 @@ pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator {
3531 }3541 }
3532}3542}
35333543
3534pub fn declIteratorInner(zir: Zir, extra_index: usize, decls_len: u32) DeclIterator {
3535 const bit_bags_count = std.math.divCeil(usize, decls_len, 8) catch unreachable;
3536 return .{
3537 .zir = zir,
3538 .extra_index = extra_index + bit_bags_count,
3539 .bit_bag_index = extra_index,
3540 .cur_bit_bag = undefined,
3541 .decl_i = 0,
3542 .decls_len = decls_len,
3543 };
3544}
3545
3546/// The iterator would have to allocate memory anyway to iterate. So here we populate3544/// The iterator would have to allocate memory anyway to iterate. So here we populate
3547/// an ArrayList as the result.3545/// an ArrayList as the result.
3548pub fn findDecls(zir: Zir, list: *std.ArrayList(Inst.Index), decl_sub_index: ExtraIndex) !void {3546pub fn findDecls(zir: Zir, list: *std.ArrayList(Inst.Index), decl_inst: Zir.Inst.Index) !void {
3549 const block_inst: Zir.Inst.Index = @enumFromInt(zir.extra[@intFromEnum(decl_sub_index) + 6]);
3550 list.clearRetainingCapacity();3547 list.clearRetainingCapacity();
3548 const declaration, const extra_end = zir.getDeclaration(decl_inst);
3549 const bodies = declaration.getBodies(extra_end, zir);
35513550
3552 return zir.findDeclsInner(list, block_inst);3551 try zir.findDeclsBody(list, bodies.value_body);
3552 if (bodies.align_body) |b| try zir.findDeclsBody(list, b);
3553 if (bodies.linksection_body) |b| try zir.findDeclsBody(list, b);
3554 if (bodies.addrspace_body) |b| try zir.findDeclsBody(list, b);
3553}3555}
35543556
3555fn findDeclsInner(3557fn findDeclsInner(
...@@ -3791,8 +3793,17 @@ pub fn getParamBody(zir: Zir, fn_inst: Inst.Index) []const Zir.Inst.Index {...@@ -3791,8 +3793,17 @@ pub fn getParamBody(zir: Zir, fn_inst: Inst.Index) []const Zir.Inst.Index {
3791 else => unreachable,3793 else => unreachable,
3792 };3794 };
37933795
3794 const param_block = zir.extraData(Inst.Block, datas[@intFromEnum(param_block_index)].pl_node.payload_index);3796 switch (tags[@intFromEnum(param_block_index)]) {
3795 return zir.bodySlice(param_block.end, param_block.data.body_len);3797 .block, .block_comptime, .block_inline => {
3798 const param_block = zir.extraData(Inst.Block, datas[@intFromEnum(param_block_index)].pl_node.payload_index);
3799 return zir.bodySlice(param_block.end, param_block.data.body_len);
3800 },
3801 .declaration => {
3802 const decl, const extra_end = zir.getDeclaration(param_block_index);
3803 return decl.getBodies(extra_end, zir).value_body;
3804 },
3805 else => unreachable,
3806 }
3796}3807}
37973808
3798pub fn getFnInfo(zir: Zir, fn_inst: Inst.Index) FnInfo {3809pub fn getFnInfo(zir: Zir, fn_inst: Inst.Index) FnInfo {
...@@ -3888,12 +3899,17 @@ pub fn getFnInfo(zir: Zir, fn_inst: Inst.Index) FnInfo {...@@ -3888,12 +3899,17 @@ pub fn getFnInfo(zir: Zir, fn_inst: Inst.Index) FnInfo {
3888 },3899 },
3889 else => unreachable,3900 else => unreachable,
3890 };3901 };
3891 switch (tags[@intFromEnum(info.param_block)]) {3902 const param_body = switch (tags[@intFromEnum(info.param_block)]) {
3892 .block, .block_comptime, .block_inline => {}, // OK3903 .block, .block_comptime, .block_inline => param_body: {
3893 else => unreachable, // assertion failure3904 const param_block = zir.extraData(Inst.Block, datas[@intFromEnum(info.param_block)].pl_node.payload_index);
3894 }3905 break :param_body zir.bodySlice(param_block.end, param_block.data.body_len);
3895 const param_block = zir.extraData(Inst.Block, datas[@intFromEnum(info.param_block)].pl_node.payload_index);3906 },
3896 const param_body = zir.bodySlice(param_block.end, param_block.data.body_len);3907 .declaration => param_body: {
3908 const decl, const extra_end = zir.getDeclaration(info.param_block);
3909 break :param_body decl.getBodies(extra_end, zir).value_body;
3910 },
3911 else => unreachable,
3912 };
3897 var total_params_len: u32 = 0;3913 var total_params_len: u32 = 0;
3898 for (param_body) |inst| {3914 for (param_body) |inst| {
3899 switch (tags[@intFromEnum(inst)]) {3915 switch (tags[@intFromEnum(inst)]) {
...@@ -3912,3 +3928,13 @@ pub fn getFnInfo(zir: Zir, fn_inst: Inst.Index) FnInfo {...@@ -3912,3 +3928,13 @@ pub fn getFnInfo(zir: Zir, fn_inst: Inst.Index) FnInfo {
3912 .total_params_len = total_params_len,3928 .total_params_len = total_params_len,
3913 };3929 };
3914}3930}
3931
3932pub fn getDeclaration(zir: Zir, inst: Zir.Inst.Index) struct { Inst.Declaration, u32 } {
3933 assert(zir.instructions.items(.tag)[@intFromEnum(inst)] == .declaration);
3934 const pl_node = zir.instructions.items(.data)[@intFromEnum(inst)].pl_node;
3935 const extra = zir.extraData(Inst.Declaration, pl_node.payload_index);
3936 return .{
3937 extra.data,
3938 @intCast(extra.end),
3939 };
3940}
src/main.zig+3-14
...@@ -6855,10 +6855,7 @@ pub fn cmdChangelist(...@@ -6855,10 +6855,7 @@ pub fn cmdChangelist(
6855 var inst_map: std.AutoHashMapUnmanaged(Zir.Inst.Index, Zir.Inst.Index) = .{};6855 var inst_map: std.AutoHashMapUnmanaged(Zir.Inst.Index, Zir.Inst.Index) = .{};
6856 defer inst_map.deinit(gpa);6856 defer inst_map.deinit(gpa);
68576857
6858 var extra_map: std.AutoHashMapUnmanaged(Zir.ExtraIndex, Zir.ExtraIndex) = .{};6858 try Module.mapOldZirToNew(gpa, old_zir, file.zir, &inst_map);
6859 defer extra_map.deinit(gpa);
6860
6861 try Module.mapOldZirToNew(gpa, old_zir, file.zir, &inst_map, &extra_map);
68626859
6863 var bw = io.bufferedWriter(io.getStdOut().writer());6860 var bw = io.bufferedWriter(io.getStdOut().writer());
6864 const stdout = bw.writer();6861 const stdout = bw.writer();
...@@ -6867,16 +6864,8 @@ pub fn cmdChangelist(...@@ -6867,16 +6864,8 @@ pub fn cmdChangelist(
6867 var it = inst_map.iterator();6864 var it = inst_map.iterator();
6868 while (it.next()) |entry| {6865 while (it.next()) |entry| {
6869 try stdout.print(" %{d} => %{d}\n", .{6866 try stdout.print(" %{d} => %{d}\n", .{
6870 entry.key_ptr.*, entry.value_ptr.*,6867 @intFromEnum(entry.key_ptr.*),
6871 });6868 @intFromEnum(entry.value_ptr.*),
6872 }
6873 }
6874 {
6875 try stdout.print("Extra mappings:\n", .{});
6876 var it = extra_map.iterator();
6877 while (it.next()) |entry| {
6878 try stdout.print(" {d} => {d}\n", .{
6879 entry.key_ptr.*, entry.value_ptr.*,
6880 });6869 });
6881 }6870 }
6882 }6871 }
src/print_zir.zig+67-122
...@@ -521,6 +521,8 @@ const Writer = struct {...@@ -521,6 +521,8 @@ const Writer = struct {
521 .@"defer" => try self.writeDefer(stream, inst),521 .@"defer" => try self.writeDefer(stream, inst),
522 .defer_err_code => try self.writeDeferErrCode(stream, inst),522 .defer_err_code => try self.writeDeferErrCode(stream, inst),
523523
524 .declaration => try self.writeDeclaration(stream, inst),
525
524 .extended => try self.writeExtended(stream, inst),526 .extended => try self.writeExtended(stream, inst),
525 }527 }
526 }528 }
...@@ -1454,8 +1456,9 @@ const Writer = struct {...@@ -1454,8 +1456,9 @@ const Writer = struct {
14541456
1455 try stream.writeAll("{\n");1457 try stream.writeAll("{\n");
1456 self.indent += 2;1458 self.indent += 2;
1457 extra_index = try self.writeDecls(stream, decls_len, extra_index);1459 try self.writeBody(stream, self.code.bodySlice(extra_index, decls_len));
1458 self.indent -= 2;1460 self.indent -= 2;
1461 extra_index += decls_len;
1459 try stream.writeByteNTimes(' ', self.indent);1462 try stream.writeByteNTimes(' ', self.indent);
1460 try stream.writeAll("}, ");1463 try stream.writeAll("}, ");
1461 }1464 }
...@@ -1634,8 +1637,9 @@ const Writer = struct {...@@ -1634,8 +1637,9 @@ const Writer = struct {
16341637
1635 try stream.writeAll("{\n");1638 try stream.writeAll("{\n");
1636 self.indent += 2;1639 self.indent += 2;
1637 extra_index = try self.writeDecls(stream, decls_len, extra_index);1640 try self.writeBody(stream, self.code.bodySlice(extra_index, decls_len));
1638 self.indent -= 2;1641 self.indent -= 2;
1642 extra_index += decls_len;
1639 try stream.writeByteNTimes(' ', self.indent);1643 try stream.writeByteNTimes(' ', self.indent);
1640 try stream.writeAll("}");1644 try stream.writeAll("}");
1641 }1645 }
...@@ -1727,124 +1731,6 @@ const Writer = struct {...@@ -1727,124 +1731,6 @@ const Writer = struct {
1727 try self.writeSrcNode(stream, src_node);1731 try self.writeSrcNode(stream, src_node);
1728 }1732 }
17291733
1730 fn writeDecls(self: *Writer, stream: anytype, decls_len: u32, extra_start: usize) !usize {
1731 const parent_decl_node = self.parent_decl_node;
1732 const bit_bags_count = std.math.divCeil(usize, decls_len, 8) catch unreachable;
1733 var extra_index = extra_start + bit_bags_count;
1734 var bit_bag_index: usize = extra_start;
1735 var cur_bit_bag: u32 = undefined;
1736 var decl_i: u32 = 0;
1737 while (decl_i < decls_len) : (decl_i += 1) {
1738 if (decl_i % 8 == 0) {
1739 cur_bit_bag = self.code.extra[bit_bag_index];
1740 bit_bag_index += 1;
1741 }
1742 const is_pub = @as(u1, @truncate(cur_bit_bag)) != 0;
1743 cur_bit_bag >>= 1;
1744 const is_exported = @as(u1, @truncate(cur_bit_bag)) != 0;
1745 cur_bit_bag >>= 1;
1746 const has_align = @as(u1, @truncate(cur_bit_bag)) != 0;
1747 cur_bit_bag >>= 1;
1748 const has_section_or_addrspace = @as(u1, @truncate(cur_bit_bag)) != 0;
1749 cur_bit_bag >>= 1;
1750
1751 const sub_index = extra_index;
1752
1753 const hash_u32s = self.code.extra[extra_index..][0..4];
1754 extra_index += 4;
1755 const line = self.code.extra[extra_index];
1756 extra_index += 1;
1757 const decl_name_index = self.code.extra[extra_index];
1758 extra_index += 1;
1759 const decl_index: Zir.Inst.Index = @enumFromInt(self.code.extra[extra_index]);
1760 extra_index += 1;
1761 const doc_comment_index: Zir.NullTerminatedString = @enumFromInt(self.code.extra[extra_index]);
1762 extra_index += 1;
1763
1764 const align_inst: Zir.Inst.Ref = if (!has_align) .none else inst: {
1765 const inst = @as(Zir.Inst.Ref, @enumFromInt(self.code.extra[extra_index]));
1766 extra_index += 1;
1767 break :inst inst;
1768 };
1769 const section_inst: Zir.Inst.Ref = if (!has_section_or_addrspace) .none else inst: {
1770 const inst = @as(Zir.Inst.Ref, @enumFromInt(self.code.extra[extra_index]));
1771 extra_index += 1;
1772 break :inst inst;
1773 };
1774 const addrspace_inst: Zir.Inst.Ref = if (!has_section_or_addrspace) .none else inst: {
1775 const inst = @as(Zir.Inst.Ref, @enumFromInt(self.code.extra[extra_index]));
1776 extra_index += 1;
1777 break :inst inst;
1778 };
1779
1780 const pub_str = if (is_pub) "pub " else "";
1781 const hash_bytes: [16]u8 = @bitCast(hash_u32s.*);
1782 if (decl_name_index == 0) {
1783 try stream.writeByteNTimes(' ', self.indent);
1784 const name = if (is_exported) "usingnamespace" else "comptime";
1785 try stream.writeAll(pub_str);
1786 try stream.writeAll(name);
1787 } else if (decl_name_index == 1) {
1788 try stream.writeByteNTimes(' ', self.indent);
1789 try stream.writeAll("test");
1790 } else if (decl_name_index == 2) {
1791 try stream.writeByteNTimes(' ', self.indent);
1792 try stream.print("[{d}] decltest {s}", .{ sub_index, self.code.nullTerminatedString(doc_comment_index) });
1793 } else {
1794 const raw_decl_name = self.code.nullTerminatedString(@enumFromInt(decl_name_index));
1795 const decl_name = if (raw_decl_name.len == 0)
1796 self.code.nullTerminatedString(@enumFromInt(decl_name_index + 1))
1797 else
1798 raw_decl_name;
1799 const test_str = if (raw_decl_name.len == 0) "test \"" else "";
1800 const export_str = if (is_exported) "export " else "";
1801
1802 try self.writeDocComment(stream, doc_comment_index);
1803
1804 try stream.writeByteNTimes(' ', self.indent);
1805 const endquote_if_test: []const u8 = if (raw_decl_name.len == 0) "\"" else "";
1806 try stream.print("[{d}] {s}{s}{s}{}{s}", .{
1807 sub_index, pub_str, test_str, export_str, std.zig.fmtId(decl_name), endquote_if_test,
1808 });
1809 if (align_inst != .none) {
1810 try stream.writeAll(" align(");
1811 try self.writeInstRef(stream, align_inst);
1812 try stream.writeAll(")");
1813 }
1814 if (addrspace_inst != .none) {
1815 try stream.writeAll(" addrspace(");
1816 try self.writeInstRef(stream, addrspace_inst);
1817 try stream.writeAll(")");
1818 }
1819 if (section_inst != .none) {
1820 try stream.writeAll(" linksection(");
1821 try self.writeInstRef(stream, section_inst);
1822 try stream.writeAll(")");
1823 }
1824 }
1825
1826 if (self.recurse_decls) {
1827 const tag = self.code.instructions.items(.tag)[@intFromEnum(decl_index)];
1828 try stream.print(" line({d}) hash({}): %{d} = {s}(", .{
1829 line, std.fmt.fmtSliceHexLower(&hash_bytes), @intFromEnum(decl_index), @tagName(tag),
1830 });
1831
1832 const decl_block_inst_data = self.code.instructions.items(.data)[@intFromEnum(decl_index)].pl_node;
1833 const sub_decl_node_off = decl_block_inst_data.src_node;
1834 self.parent_decl_node = self.relativeToNodeIndex(sub_decl_node_off);
1835 try self.writePlNodeBlockWithoutSrc(stream, decl_index);
1836 self.parent_decl_node = parent_decl_node;
1837 try self.writeSrc(stream, decl_block_inst_data.src());
1838 try stream.writeAll("\n");
1839 } else {
1840 try stream.print(" line({d}) hash({}): %{d} = ...\n", .{
1841 line, std.fmt.fmtSliceHexLower(&hash_bytes), @intFromEnum(decl_index),
1842 });
1843 }
1844 }
1845 return extra_index;
1846 }
1847
1848 fn writeEnumDecl(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void {1734 fn writeEnumDecl(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void {
1849 const small = @as(Zir.Inst.EnumDecl.Small, @bitCast(extended.small));1735 const small = @as(Zir.Inst.EnumDecl.Small, @bitCast(extended.small));
1850 var extra_index: usize = extended.operand;1736 var extra_index: usize = extended.operand;
...@@ -1891,8 +1777,9 @@ const Writer = struct {...@@ -1891,8 +1777,9 @@ const Writer = struct {
18911777
1892 try stream.writeAll("{\n");1778 try stream.writeAll("{\n");
1893 self.indent += 2;1779 self.indent += 2;
1894 extra_index = try self.writeDecls(stream, decls_len, extra_index);1780 try self.writeBody(stream, self.code.bodySlice(extra_index, decls_len));
1895 self.indent -= 2;1781 self.indent -= 2;
1782 extra_index += decls_len;
1896 try stream.writeByteNTimes(' ', self.indent);1783 try stream.writeByteNTimes(' ', self.indent);
1897 try stream.writeAll("}, ");1784 try stream.writeAll("}, ");
1898 }1785 }
...@@ -1988,7 +1875,7 @@ const Writer = struct {...@@ -1988,7 +1875,7 @@ const Writer = struct {
19881875
1989 try stream.writeAll("{\n");1876 try stream.writeAll("{\n");
1990 self.indent += 2;1877 self.indent += 2;
1991 _ = try self.writeDecls(stream, decls_len, extra_index);1878 try self.writeBody(stream, self.code.bodySlice(extra_index, decls_len));
1992 self.indent -= 2;1879 self.indent -= 2;
1993 try stream.writeByteNTimes(' ', self.indent);1880 try stream.writeByteNTimes(' ', self.indent);
1994 try stream.writeAll("})");1881 try stream.writeAll("})");
...@@ -2762,6 +2649,64 @@ const Writer = struct {...@@ -2762,6 +2649,64 @@ const Writer = struct {
2762 try stream.writeByte(')');2649 try stream.writeByte(')');
2763 }2650 }
27642651
2652 fn writeDeclaration(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {
2653 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
2654 const extra = self.code.extraData(Zir.Inst.Declaration, inst_data.payload_index);
2655 const doc_comment: ?Zir.NullTerminatedString = if (extra.data.flags.has_doc_comment) dc: {
2656 break :dc @enumFromInt(self.code.extra[extra.end]);
2657 } else null;
2658 if (extra.data.flags.is_pub) try stream.writeAll("pub ");
2659 if (extra.data.flags.is_export) try stream.writeAll("export ");
2660 switch (extra.data.name) {
2661 .@"comptime" => try stream.writeAll("comptime"),
2662 .@"usingnamespace" => try stream.writeAll("usingnamespace"),
2663 .unnamed_test => try stream.writeAll("test"),
2664 .decltest => try stream.print("decltest '{s}'", .{self.code.nullTerminatedString(doc_comment.?)}),
2665 _ => {
2666 const name = extra.data.name.toString(self.code).?;
2667 const prefix = if (extra.data.name.isNamedTest(self.code)) "test " else "";
2668 try stream.print("{s}'{s}'", .{ prefix, self.code.nullTerminatedString(name) });
2669 },
2670 }
2671 const src_hash_arr: [4]u32 = .{
2672 extra.data.src_hash_0,
2673 extra.data.src_hash_1,
2674 extra.data.src_hash_2,
2675 extra.data.src_hash_3,
2676 };
2677 const src_hash_bytes: [16]u8 = @bitCast(src_hash_arr);
2678 try stream.print(" line(+{d}) hash({})", .{ extra.data.line_offset, std.fmt.fmtSliceHexLower(&src_hash_bytes) });
2679
2680 {
2681 const prev_parent_decl_node = self.parent_decl_node;
2682 defer self.parent_decl_node = prev_parent_decl_node;
2683 self.parent_decl_node = self.relativeToNodeIndex(inst_data.src_node);
2684
2685 const bodies = extra.data.getBodies(@intCast(extra.end), self.code);
2686
2687 try stream.writeAll(" value=");
2688 try self.writeBracedDecl(stream, bodies.value_body);
2689
2690 if (bodies.align_body) |b| {
2691 try stream.writeAll(" align=");
2692 try self.writeBracedDecl(stream, b);
2693 }
2694
2695 if (bodies.linksection_body) |b| {
2696 try stream.writeAll(" linksection=");
2697 try self.writeBracedDecl(stream, b);
2698 }
2699
2700 if (bodies.addrspace_body) |b| {
2701 try stream.writeAll(" addrspace=");
2702 try self.writeBracedDecl(stream, b);
2703 }
2704 }
2705
2706 try stream.writeAll(") ");
2707 try self.writeSrc(stream, inst_data.src());
2708 }
2709
2765 fn writeInstRef(self: *Writer, stream: anytype, ref: Zir.Inst.Ref) !void {2710 fn writeInstRef(self: *Writer, stream: anytype, ref: Zir.Inst.Ref) !void {
2766 if (ref == .none) {2711 if (ref == .none) {
2767 return stream.writeAll(".none");2712 return stream.writeAll(".none");