| author | |
| committer | |
| log | b96fb858c88b97617e6fa0e3c6966a8e900caf7f |
| tree | e1729e12109e85e1ed2d4b7eb06187206e9bd8d3 |
| parent | 8a0429e885489eac497aa97fdfcaaa1befb2b6d4 |
| parent | 06d8bb32e3edfb4a26c6d3ecdf198574f4bd3f87 |
| signature |
InternPool: introduce TrackedInst to prepare for incremental compilation9 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 | 86 | |
| 87 | 87 | Zir.Inst.Ref, |
| 88 | 88 | Zir.Inst.Index, |
| 89 | Zir.Inst.Declaration.Name, | |
| 89 | 90 | Zir.NullTerminatedString, |
| 90 | 91 | => @intFromEnum(@field(extra, field.name)), |
| 91 | 92 | |
| ... | ... | @@ -95,6 +96,7 @@ fn setExtra(astgen: *AstGen, index: usize, extra: anytype) void { |
| 95 | 96 | Zir.Inst.SwitchBlock.Bits, |
| 96 | 97 | Zir.Inst.SwitchBlockErrUnion.Bits, |
| 97 | 98 | Zir.Inst.FuncFancy.Bits, |
| 99 | Zir.Inst.Declaration.Flags, | |
| 98 | 100 | => @bitCast(@field(extra, field.name)), |
| 99 | 101 | |
| 100 | 102 | else => @compileError("bad field type"), |
| ... | ... | @@ -132,8 +134,8 @@ pub fn generate(gpa: Allocator, tree: Ast) Allocator.Error!Zir { |
| 132 | 134 | }; |
| 133 | 135 | defer astgen.deinit(gpa); |
| 134 | 136 | |
| 135 | // String table indexes 0, 1, 2 are reserved for special meaning. | |
| 136 | try astgen.string_bytes.appendSlice(gpa, &[_]u8{ 0, 0, 0 }); | |
| 137 | // String table index 0 is reserved for `NullTerminatedString.empty`. | |
| 138 | try astgen.string_bytes.append(gpa, 0); | |
| 137 | 139 | |
| 138 | 140 | // We expect at least as many ZIR instructions and extra data items |
| 139 | 141 | // as AST nodes. |
| ... | ... | @@ -355,8 +357,13 @@ const ResultInfo = struct { |
| 355 | 357 | }; |
| 356 | 358 | }; |
| 357 | 359 | |
| 360 | /// TODO: modify Sema to remove in favour of `coerced_align_ri` | |
| 358 | 361 | const align_ri: ResultInfo = .{ .rl = .{ .ty = .u29_type } }; |
| 359 | 362 | const coerced_align_ri: ResultInfo = .{ .rl = .{ .coerced_ty = .u29_type } }; |
| 363 | /// TODO: modify Sema to remove in favour of `coerced_addrspace_ri` | |
| 364 | const addrspace_ri: ResultInfo = .{ .rl = .{ .ty = .address_space_type } }; | |
| 365 | const coerced_addrspace_ri: ResultInfo = .{ .rl = .{ .coerced_ty = .address_space_type } }; | |
| 366 | const coerced_linksection_ri: ResultInfo = .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }; | |
| 360 | 367 | const bool_ri: ResultInfo = .{ .rl = .{ .ty = .bool_type } }; |
| 361 | 368 | const type_ri: ResultInfo = .{ .rl = .{ .ty = .type_type } }; |
| 362 | 369 | const 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 | 2599 | .block, |
| 2593 | 2600 | .block_comptime, |
| 2594 | 2601 | .block_inline, |
| 2602 | .declaration, | |
| 2595 | 2603 | .suspend_block, |
| 2596 | 2604 | .loop, |
| 2597 | 2605 | .bool_br_and, |
| ... | ... | @@ -3783,7 +3791,7 @@ fn ptrType( |
| 3783 | 3791 | gz.astgen.source_line = source_line; |
| 3784 | 3792 | gz.astgen.source_column = source_column; |
| 3785 | 3793 | |
| 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 | 3795 | trailing_count += 1; |
| 3788 | 3796 | } |
| 3789 | 3797 | if (ptr_info.ast.align_node != 0) { |
| ... | ... | @@ -3899,8 +3907,6 @@ fn arrayTypeSentinel(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node. |
| 3899 | 3907 | const WipMembers = struct { |
| 3900 | 3908 | payload: *ArrayListUnmanaged(u32), |
| 3901 | 3909 | payload_top: usize, |
| 3902 | decls_start: u32, | |
| 3903 | decls_end: u32, | |
| 3904 | 3910 | field_bits_start: u32, |
| 3905 | 3911 | fields_start: u32, |
| 3906 | 3912 | fields_end: u32, |
| ... | ... | @@ -3908,43 +3914,27 @@ const WipMembers = struct { |
| 3908 | 3914 | field_index: u32 = 0, |
| 3909 | 3915 | |
| 3910 | 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; | |
| 3917 | 3917 | |
| 3918 | 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 | 3919 | const payload_top: u32 = @intCast(payload.items.len); |
| 3920 | const decls_start = payload_top + (decl_count + decls_per_u32 - 1) / decls_per_u32; | |
| 3921 | const field_bits_start = decls_start + decl_count * max_decl_size; | |
| 3920 | const field_bits_start = payload_top + decl_count; | |
| 3922 | 3921 | const fields_start = field_bits_start + if (bits_per_field > 0) blk: { |
| 3923 | 3922 | const fields_per_u32 = 32 / bits_per_field; |
| 3924 | 3923 | break :blk (field_count + fields_per_u32 - 1) / fields_per_u32; |
| 3925 | 3924 | } else 0; |
| 3926 | 3925 | const payload_end = fields_start + field_count * max_field_size; |
| 3927 | 3926 | try payload.resize(gpa, payload_end); |
| 3928 | return Self{ | |
| 3927 | return .{ | |
| 3929 | 3928 | .payload = payload, |
| 3930 | 3929 | .payload_top = payload_top, |
| 3931 | .decls_start = decls_start, | |
| 3932 | 3930 | .field_bits_start = field_bits_start, |
| 3933 | 3931 | .fields_start = fields_start, |
| 3934 | .decls_end = decls_start, | |
| 3935 | 3932 | .fields_end = fields_start, |
| 3936 | 3933 | }; |
| 3937 | 3934 | } |
| 3938 | 3935 | |
| 3939 | fn nextDecl(self: *Self, is_pub: bool, is_export: bool, has_align: bool, has_section_or_addrspace: bool) void { | |
| 3940 | const index = self.payload_top + self.decl_index / decls_per_u32; | |
| 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); | |
| 3936 | fn nextDecl(self: *Self, decl_inst: Zir.Inst.Index) void { | |
| 3937 | self.payload.items[self.payload_top + self.decl_index] = @intFromEnum(decl_inst); | |
| 3948 | 3938 | self.decl_index += 1; |
| 3949 | 3939 | } |
| 3950 | 3940 | |
| ... | ... | @@ -3962,18 +3952,6 @@ const WipMembers = struct { |
| 3962 | 3952 | self.field_index += 1; |
| 3963 | 3953 | } |
| 3964 | 3954 | |
| 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 | 3955 | fn appendToField(self: *Self, data: u32) void { |
| 3978 | 3956 | assert(self.fields_end < self.payload.items.len); |
| 3979 | 3957 | self.payload.items[self.fields_end] = data; |
| ... | ... | @@ -3981,11 +3959,6 @@ const WipMembers = struct { |
| 3981 | 3959 | } |
| 3982 | 3960 | |
| 3983 | 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 | 3962 | if (bits_per_field > 0) { |
| 3990 | 3963 | const fields_per_u32 = 32 / bits_per_field; |
| 3991 | 3964 | const empty_field_slots = fields_per_u32 - (self.field_index % fields_per_u32); |
| ... | ... | @@ -3997,7 +3970,7 @@ const WipMembers = struct { |
| 3997 | 3970 | } |
| 3998 | 3971 | |
| 3999 | 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 | } |
| 4002 | 3975 | |
| 4003 | 3976 | fn fieldsSlice(self: *Self) []u32 { |
| ... | ... | @@ -4023,11 +3996,10 @@ fn fnDecl( |
| 4023 | 3996 | |
| 4024 | 3997 | // missing function name already happened in scanDecls() |
| 4025 | 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); | |
| 4027 | 3999 | |
| 4028 | 4000 | // We insert this at the beginning so that its instruction index marks the |
| 4029 | 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 | 4003 | astgen.advanceSourceCursorToNode(decl_node); |
| 4032 | 4004 | |
| 4033 | 4005 | var decl_gz: GenZir = .{ |
| ... | ... | @@ -4072,8 +4044,7 @@ fn fnDecl( |
| 4072 | 4044 | |
| 4073 | 4045 | const doc_comment_index = try astgen.docCommentAsString(fn_proto.firstToken()); |
| 4074 | 4046 | |
| 4075 | // align, linksection, and addrspace is passed in the func instruction in this case. | |
| 4076 | wip_members.nextDecl(is_pub, is_export, false, false); | |
| 4047 | wip_members.nextDecl(decl_inst); | |
| 4077 | 4048 | |
| 4078 | 4049 | var noalias_bits: u32 = 0; |
| 4079 | 4050 | var params_scope = &fn_gz.base; |
| ... | ... | @@ -4213,7 +4184,7 @@ fn fnDecl( |
| 4213 | 4184 | var addrspace_gz = decl_gz.makeSubBlock(params_scope); |
| 4214 | 4185 | defer addrspace_gz.unstack(); |
| 4215 | 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 | 4188 | if (addrspace_gz.instructionsSlice().len == 0) { |
| 4218 | 4189 | // In this case we will send a len=0 body which can be encoded more efficiently. |
| 4219 | 4190 | break :inst inst; |
| ... | ... | @@ -4298,7 +4269,7 @@ fn fnDecl( |
| 4298 | 4269 | .section_gz = &section_gz, |
| 4299 | 4270 | .addrspace_ref = addrspace_ref, |
| 4300 | 4271 | .addrspace_gz = &addrspace_gz, |
| 4301 | .param_block = block_inst, | |
| 4272 | .param_block = decl_inst, | |
| 4302 | 4273 | .body_gz = null, |
| 4303 | 4274 | .lib_name = lib_name, |
| 4304 | 4275 | .is_var_args = is_var_args, |
| ... | ... | @@ -4349,7 +4320,7 @@ fn fnDecl( |
| 4349 | 4320 | .addrspace_gz = &addrspace_gz, |
| 4350 | 4321 | .lbrace_line = lbrace_line, |
| 4351 | 4322 | .lbrace_column = lbrace_column, |
| 4352 | .param_block = block_inst, | |
| 4323 | .param_block = decl_inst, | |
| 4353 | 4324 | .body_gz = &fn_gz, |
| 4354 | 4325 | .lib_name = lib_name, |
| 4355 | 4326 | .is_var_args = is_var_args, |
| ... | ... | @@ -4363,20 +4334,21 @@ fn fnDecl( |
| 4363 | 4334 | |
| 4364 | 4335 | // We add this at the end so that its instruction index marks the end range |
| 4365 | 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); | |
| 4367 | try decl_gz.setBlockBody(block_inst); | |
| 4368 | ||
| 4369 | { | |
| 4370 | const contents_hash align(@alignOf(u32)) = std.zig.hashSrc(tree.getNodeSource(decl_node)); | |
| 4371 | wip_members.appendToDeclSlice(std.mem.bytesAsSlice(u32, &contents_hash)); | |
| 4372 | } | |
| 4373 | { | |
| 4374 | const line_delta = decl_gz.decl_line - gz.decl_line; | |
| 4375 | wip_members.appendToDecl(line_delta); | |
| 4376 | } | |
| 4377 | wip_members.appendToDecl(@intFromEnum(fn_name_str_index)); | |
| 4378 | wip_members.appendToDecl(@intFromEnum(block_inst)); | |
| 4379 | wip_members.appendToDecl(@intFromEnum(doc_comment_index)); | |
| 4337 | _ = try decl_gz.addBreak(.break_inline, decl_inst, func_inst); | |
| 4338 | ||
| 4339 | try setDeclaration( | |
| 4340 | decl_inst, | |
| 4341 | std.zig.hashSrc(tree.getNodeSource(decl_node)), | |
| 4342 | .{ .named = fn_name_token }, | |
| 4343 | decl_gz.decl_line - gz.decl_line, | |
| 4344 | is_pub, | |
| 4345 | is_export, | |
| 4346 | doc_comment_index, | |
| 4347 | &decl_gz, | |
| 4348 | // align, linksection, and addrspace are passed in the func instruction in this case. | |
| 4349 | // TODO: move them from the function instruction to the declaration instruction? | |
| 4350 | null, | |
| 4351 | ); | |
| 4380 | 4352 | } |
| 4381 | 4353 | |
| 4382 | 4354 | fn globalVarDecl( |
| ... | ... | @@ -4393,10 +4365,9 @@ fn globalVarDecl( |
| 4393 | 4365 | const is_mutable = token_tags[var_decl.ast.mut_token] == .keyword_var; |
| 4394 | 4366 | // We do this at the beginning so that the instruction index marks the range start |
| 4395 | 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); | |
| 4397 | 4369 | |
| 4398 | 4370 | const name_token = var_decl.ast.mut_token + 1; |
| 4399 | const name_str_index = try astgen.identAsString(name_token); | |
| 4400 | 4371 | astgen.advanceSourceCursorToNode(node); |
| 4401 | 4372 | |
| 4402 | 4373 | var block_scope: GenZir = .{ |
| ... | ... | @@ -4420,17 +4391,7 @@ fn globalVarDecl( |
| 4420 | 4391 | const maybe_extern_token = var_decl.extern_export_token orelse break :blk false; |
| 4421 | 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: { | |
| 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); | |
| 4394 | wip_members.nextDecl(decl_inst); | |
| 4434 | 4395 | |
| 4435 | 4396 | const is_threadlocal = if (var_decl.threadlocal_token) |tok| blk: { |
| 4436 | 4397 | if (!is_mutable) { |
| ... | ... | @@ -4513,29 +4474,44 @@ fn globalVarDecl( |
| 4513 | 4474 | } else { |
| 4514 | 4475 | return astgen.failNode(node, "unable to infer variable type", .{}); |
| 4515 | 4476 | }; |
| 4477 | ||
| 4516 | 4478 | // We do this at the end so that the instruction index marks the end |
| 4517 | 4479 | // range of a top level declaration. |
| 4518 | _ = try block_scope.addBreakWithSrcNode(.break_inline, block_inst, var_inst, node); | |
| 4519 | try block_scope.setBlockBody(block_inst); | |
| 4480 | _ = try block_scope.addBreakWithSrcNode(.break_inline, decl_inst, var_inst, node); | |
| 4520 | 4481 | |
| 4521 | { | |
| 4522 | const contents_hash align(@alignOf(u32)) = std.zig.hashSrc(tree.getNodeSource(node)); | |
| 4523 | wip_members.appendToDeclSlice(std.mem.bytesAsSlice(u32, &contents_hash)); | |
| 4482 | var align_gz = block_scope.makeSubBlock(scope); | |
| 4483 | if (var_decl.ast.align_node != 0) { | |
| 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 | { | |
| 4526 | const line_delta = block_scope.decl_line - gz.decl_line; | |
| 4527 | wip_members.appendToDecl(line_delta); | |
| 4528 | } | |
| 4529 | wip_members.appendToDecl(@intFromEnum(name_str_index)); | |
| 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)); | |
| 4487 | ||
| 4488 | var linksection_gz = align_gz.makeSubBlock(scope); | |
| 4489 | if (var_decl.ast.section_node != 0) { | |
| 4490 | const linksection_inst = try expr(&linksection_gz, &linksection_gz.base, coerced_linksection_ri, var_decl.ast.section_node); | |
| 4491 | _ = try linksection_gz.addBreakWithSrcNode(.break_inline, decl_inst, linksection_inst, node); | |
| 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 | } |
| 4540 | 4516 | |
| 4541 | 4517 | fn comptimeDecl( |
| ... | ... | @@ -4551,8 +4527,8 @@ fn comptimeDecl( |
| 4551 | 4527 | |
| 4552 | 4528 | // Up top so the ZIR instruction index marks the start range of this |
| 4553 | 4529 | // top-level declaration. |
| 4554 | const block_inst = try gz.makeBlockInst(.block_inline, node); | |
| 4555 | wip_members.nextDecl(false, false, false, false); | |
| 4530 | const decl_inst = try gz.makeBlockInst(.declaration, node); | |
| 4531 | wip_members.nextDecl(decl_inst); | |
| 4556 | 4532 | astgen.advanceSourceCursorToNode(node); |
| 4557 | 4533 | |
| 4558 | 4534 | var decl_block: GenZir = .{ |
| ... | ... | @@ -4568,21 +4544,20 @@ fn comptimeDecl( |
| 4568 | 4544 | |
| 4569 | 4545 | const block_result = try expr(&decl_block, &decl_block.base, .{ .rl = .none }, body_node); |
| 4570 | 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); | |
| 4574 | 4549 | |
| 4575 | { | |
| 4576 | const contents_hash align(@alignOf(u32)) = std.zig.hashSrc(tree.getNodeSource(node)); | |
| 4577 | wip_members.appendToDeclSlice(std.mem.bytesAsSlice(u32, &contents_hash)); | |
| 4578 | } | |
| 4579 | { | |
| 4580 | const line_delta = decl_block.decl_line - gz.decl_line; | |
| 4581 | wip_members.appendToDecl(line_delta); | |
| 4582 | } | |
| 4583 | wip_members.appendToDecl(0); | |
| 4584 | wip_members.appendToDecl(@intFromEnum(block_inst)); | |
| 4585 | wip_members.appendToDecl(0); // no doc comments on comptime decls | |
| 4550 | try setDeclaration( | |
| 4551 | decl_inst, | |
| 4552 | std.zig.hashSrc(tree.getNodeSource(node)), | |
| 4553 | .@"comptime", | |
| 4554 | decl_block.decl_line - gz.decl_line, | |
| 4555 | false, | |
| 4556 | false, | |
| 4557 | .empty, | |
| 4558 | &decl_block, | |
| 4559 | null, | |
| 4560 | ); | |
| 4586 | 4561 | } |
| 4587 | 4562 | |
| 4588 | 4563 | fn usingnamespaceDecl( |
| ... | ... | @@ -4604,8 +4579,8 @@ fn usingnamespaceDecl( |
| 4604 | 4579 | }; |
| 4605 | 4580 | // Up top so the ZIR instruction index marks the start range of this |
| 4606 | 4581 | // top-level declaration. |
| 4607 | const block_inst = try gz.makeBlockInst(.block_inline, node); | |
| 4608 | wip_members.nextDecl(is_pub, true, false, false); | |
| 4582 | const decl_inst = try gz.makeBlockInst(.declaration, node); | |
| 4583 | wip_members.nextDecl(decl_inst); | |
| 4609 | 4584 | astgen.advanceSourceCursorToNode(node); |
| 4610 | 4585 | |
| 4611 | 4586 | var decl_block: GenZir = .{ |
| ... | ... | @@ -4620,20 +4595,19 @@ fn usingnamespaceDecl( |
| 4620 | 4595 | defer decl_block.unstack(); |
| 4621 | 4596 | |
| 4622 | 4597 | const namespace_inst = try typeExpr(&decl_block, &decl_block.base, type_expr); |
| 4623 | _ = try decl_block.addBreak(.break_inline, block_inst, namespace_inst); | |
| 4624 | try decl_block.setBlockBody(block_inst); | |
| 4625 | ||
| 4626 | { | |
| 4627 | const contents_hash align(@alignOf(u32)) = std.zig.hashSrc(tree.getNodeSource(node)); | |
| 4628 | wip_members.appendToDeclSlice(std.mem.bytesAsSlice(u32, &contents_hash)); | |
| 4629 | } | |
| 4630 | { | |
| 4631 | const line_delta = decl_block.decl_line - gz.decl_line; | |
| 4632 | wip_members.appendToDecl(line_delta); | |
| 4633 | } | |
| 4634 | wip_members.appendToDecl(0); | |
| 4635 | wip_members.appendToDecl(@intFromEnum(block_inst)); | |
| 4636 | wip_members.appendToDecl(0); // no doc comments on usingnamespace decls | |
| 4598 | _ = try decl_block.addBreak(.break_inline, decl_inst, namespace_inst); | |
| 4599 | ||
| 4600 | try setDeclaration( | |
| 4601 | decl_inst, | |
| 4602 | std.zig.hashSrc(tree.getNodeSource(node)), | |
| 4603 | .@"usingnamespace", | |
| 4604 | decl_block.decl_line - gz.decl_line, | |
| 4605 | is_pub, | |
| 4606 | false, | |
| 4607 | .empty, | |
| 4608 | &decl_block, | |
| 4609 | null, | |
| 4610 | ); | |
| 4637 | 4611 | } |
| 4638 | 4612 | |
| 4639 | 4613 | fn testDecl( |
| ... | ... | @@ -4649,9 +4623,9 @@ fn testDecl( |
| 4649 | 4623 | |
| 4650 | 4624 | // Up top so the ZIR instruction index marks the start range of this |
| 4651 | 4625 | // top-level declaration. |
| 4652 | const block_inst = try gz.makeBlockInst(.block_inline, node); | |
| 4626 | const decl_inst = try gz.makeBlockInst(.declaration, node); | |
| 4653 | 4627 | |
| 4654 | wip_members.nextDecl(false, false, false, false); | |
| 4628 | wip_members.nextDecl(decl_inst); | |
| 4655 | 4629 | astgen.advanceSourceCursorToNode(node); |
| 4656 | 4630 | |
| 4657 | 4631 | var decl_block: GenZir = .{ |
| ... | ... | @@ -4669,12 +4643,10 @@ fn testDecl( |
| 4669 | 4643 | const token_tags = tree.tokens.items(.tag); |
| 4670 | 4644 | const test_token = main_tokens[node]; |
| 4671 | 4645 | const test_name_token = test_token + 1; |
| 4672 | const test_name_token_tag = token_tags[test_name_token]; | |
| 4673 | const is_decltest = test_name_token_tag == .identifier; | |
| 4674 | const test_name: Zir.NullTerminatedString = blk: { | |
| 4675 | if (test_name_token_tag == .string_literal) { | |
| 4676 | break :blk try astgen.testNameString(test_name_token); | |
| 4677 | } else if (test_name_token_tag == .identifier) { | |
| 4646 | const test_name: DeclarationName = switch (token_tags[test_name_token]) { | |
| 4647 | else => .unnamed_test, | |
| 4648 | .string_literal => .{ .named_test = test_name_token }, | |
| 4649 | .identifier => blk: { | |
| 4678 | 4650 | const ident_name_raw = tree.tokenSlice(test_name_token); |
| 4679 | 4651 | |
| 4680 | 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 | 4716 | return astgen.failTok(test_name_token, "use of undeclared identifier '{s}'", .{ident_name}); |
| 4745 | 4717 | } |
| 4746 | 4718 | |
| 4747 | break :blk name_str_index; | |
| 4748 | } | |
| 4749 | // String table index 1 has a special meaning here of test decl with no name. | |
| 4750 | break :blk .unnamed_test_decl; | |
| 4719 | break :blk .{ .decltest = name_str_index }; | |
| 4720 | }, | |
| 4751 | 4721 | }; |
| 4752 | 4722 | |
| 4753 | 4723 | var fn_block: GenZir = .{ |
| ... | ... | @@ -4795,7 +4765,7 @@ fn testDecl( |
| 4795 | 4765 | |
| 4796 | 4766 | .lbrace_line = lbrace_line, |
| 4797 | 4767 | .lbrace_column = lbrace_column, |
| 4798 | .param_block = block_inst, | |
| 4768 | .param_block = decl_inst, | |
| 4799 | 4769 | .body_gz = &fn_block, |
| 4800 | 4770 | .lib_name = .empty, |
| 4801 | 4771 | .is_var_args = false, |
| ... | ... | @@ -4806,26 +4776,19 @@ fn testDecl( |
| 4806 | 4776 | .noalias_bits = 0, |
| 4807 | 4777 | }); |
| 4808 | 4778 | |
| 4809 | _ = try decl_block.addBreak(.break_inline, block_inst, func_inst); | |
| 4810 | try decl_block.setBlockBody(block_inst); | |
| 4811 | ||
| 4812 | { | |
| 4813 | const contents_hash align(@alignOf(u32)) = std.zig.hashSrc(tree.getNodeSource(node)); | |
| 4814 | wip_members.appendToDeclSlice(std.mem.bytesAsSlice(u32, &contents_hash)); | |
| 4815 | } | |
| 4816 | { | |
| 4817 | const line_delta = decl_block.decl_line - gz.decl_line; | |
| 4818 | wip_members.appendToDecl(line_delta); | |
| 4819 | } | |
| 4820 | if (is_decltest) | |
| 4821 | wip_members.appendToDecl(2) // 2 here means that it is a decltest, look at doc comment for name | |
| 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 | |
| 4779 | _ = try decl_block.addBreak(.break_inline, decl_inst, func_inst); | |
| 4780 | ||
| 4781 | try setDeclaration( | |
| 4782 | decl_inst, | |
| 4783 | std.zig.hashSrc(tree.getNodeSource(node)), | |
| 4784 | test_name, | |
| 4785 | decl_block.decl_line - gz.decl_line, | |
| 4786 | false, | |
| 4787 | false, | |
| 4788 | .empty, | |
| 4789 | &decl_block, | |
| 4790 | null, | |
| 4791 | ); | |
| 4829 | 4792 | } |
| 4830 | 4793 | |
| 4831 | 4794 | fn structDeclInner( |
| ... | ... | @@ -13524,3 +13487,106 @@ fn lowerAstErrors(astgen: *AstGen) !void { |
| 13524 | 13487 | try tree.renderError(parse_err, msg.writer(gpa)); |
| 13525 | 13488 | try astgen.appendErrorTokNotesOff(parse_err.token, extra_offset, "{s}", .{msg.items}, notes.items); |
| 13526 | 13489 | } |
| 13490 | ||
| 13491 | const 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`. | |
| 13502 | fn 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 | 2846 | return res; |
| 2847 | 2847 | }, |
| 2848 | 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 | 2852 | file, |
| 2851 | 2853 | parent_scope, |
| 2854 | try self.srcLocInfo(file, pl_node.src_node, parent_src), | |
| 2852 | 2855 | parent_src, |
| 2853 | getBlockInlineBreak(file.zir, inst) orelse { | |
| 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 | }, | |
| 2856 | file.zir.bodySlice(extra.end, extra.data.body_len), | |
| 2865 | 2857 | need_type, |
| 2866 | 2858 | call_ctx, |
| 2867 | 2859 | ); |
| ... | ... | @@ -4084,19 +4076,11 @@ fn analyzeAllDecls( |
| 4084 | 4076 | // First loop to discover decl names |
| 4085 | 4077 | { |
| 4086 | 4078 | var it = original_it; |
| 4087 | while (it.next()) |d| { | |
| 4088 | const decl_name_index: Zir.NullTerminatedString = @enumFromInt(file.zir.extra[@intFromEnum(d.sub_index) + 5]); | |
| 4089 | switch (decl_name_index) { | |
| 4090 | .empty, | |
| 4091 | .unnamed_test_decl, | |
| 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); | |
| 4079 | while (it.next()) |zir_index| { | |
| 4080 | const declaration, _ = file.zir.getDeclaration(zir_index); | |
| 4081 | if (declaration.name.isNamedTest(file.zir)) continue; | |
| 4082 | const decl_name = declaration.name.toString(file.zir) orelse continue; | |
| 4083 | try scope.insertDeclRef(self.arena, decl_name, .Pending); | |
| 4100 | 4084 | } |
| 4101 | 4085 | } |
| 4102 | 4086 | |
| ... | ... | @@ -4104,147 +4088,114 @@ fn analyzeAllDecls( |
| 4104 | 4088 | { |
| 4105 | 4089 | var it = original_it; |
| 4106 | 4090 | var decl_indexes_slot = first_decl_indexes_slot; |
| 4107 | while (it.next()) |d| : (decl_indexes_slot += 1) { | |
| 4108 | const decl_name_index = file.zir.extra[@intFromEnum(d.sub_index) + 5]; | |
| 4109 | switch (decl_name_index) { | |
| 4110 | 0 => { | |
| 4111 | const is_exported = @as(u1, @truncate(d.flags >> 1)); | |
| 4112 | switch (is_exported) { | |
| 4113 | 0 => continue, // comptime decl | |
| 4114 | 1 => { | |
| 4115 | try self.analyzeUsingnamespaceDecl( | |
| 4116 | file, | |
| 4117 | scope, | |
| 4118 | parent_src, | |
| 4119 | decl_indexes, | |
| 4120 | priv_decl_indexes, | |
| 4121 | d, | |
| 4122 | call_ctx, | |
| 4123 | ); | |
| 4124 | }, | |
| 4125 | } | |
| 4126 | }, | |
| 4127 | else => continue, | |
| 4128 | } | |
| 4091 | while (it.next()) |zir_index| : (decl_indexes_slot += 1) { | |
| 4092 | const pl_node = file.zir.instructions.items(.data)[@intFromEnum(zir_index)].pl_node; | |
| 4093 | const extra = file.zir.extraData(Zir.Inst.Declaration, pl_node.payload_index); | |
| 4094 | if (extra.data.name != .@"usingnamespace") continue; | |
| 4095 | try self.analyzeUsingnamespaceDecl( | |
| 4096 | file, | |
| 4097 | scope, | |
| 4098 | try self.srcLocInfo(file, pl_node.src_node, parent_src), | |
| 4099 | decl_indexes, | |
| 4100 | priv_decl_indexes, | |
| 4101 | extra.data, | |
| 4102 | @intCast(extra.end), | |
| 4103 | call_ctx, | |
| 4104 | ); | |
| 4129 | 4105 | } |
| 4130 | 4106 | } |
| 4131 | 4107 | |
| 4132 | 4108 | // Third loop to analyze all remaining decls |
| 4133 | var it = original_it; | |
| 4134 | while (it.next()) |d| { | |
| 4135 | const decl_name_index = file.zir.extra[@intFromEnum(d.sub_index) + 5]; | |
| 4136 | switch (decl_name_index) { | |
| 4137 | 0, 1 => continue, // skip over usingnamespace decls | |
| 4138 | 2 => continue, // skip decltests | |
| 4139 | ||
| 4140 | else => if (file.zir.string_bytes[decl_name_index] == 0) { | |
| 4141 | continue; | |
| 4142 | }, | |
| 4109 | { | |
| 4110 | var it = original_it; | |
| 4111 | while (it.next()) |zir_index| { | |
| 4112 | const pl_node = file.zir.instructions.items(.data)[@intFromEnum(zir_index)].pl_node; | |
| 4113 | const extra = file.zir.extraData(Zir.Inst.Declaration, pl_node.payload_index); | |
| 4114 | switch (extra.data.name) { | |
| 4115 | .@"comptime", .@"usingnamespace", .unnamed_test, .decltest => continue, | |
| 4116 | _ => if (extra.data.name.isNamedTest(file.zir)) continue, | |
| 4117 | } | |
| 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 | } |
| 4155 | 4131 | |
| 4156 | 4132 | // Fourth loop to analyze decltests |
| 4157 | it = original_it; | |
| 4158 | while (it.next()) |d| { | |
| 4159 | const decl_name_index = file.zir.extra[@intFromEnum(d.sub_index) + 5]; | |
| 4160 | switch (decl_name_index) { | |
| 4161 | 0, 1 => continue, // skip over usingnamespace decls | |
| 4162 | 2 => {}, | |
| 4163 | else => continue, // skip tests and normal decls | |
| 4164 | } | |
| 4165 | ||
| 4133 | var it = original_it; | |
| 4134 | while (it.next()) |zir_index| { | |
| 4135 | const pl_node = file.zir.instructions.items(.data)[@intFromEnum(zir_index)].pl_node; | |
| 4136 | const extra = file.zir.extraData(Zir.Inst.Declaration, pl_node.payload_index); | |
| 4137 | if (extra.data.name != .decltest) continue; | |
| 4166 | 4138 | try self.analyzeDecltest( |
| 4167 | 4139 | file, |
| 4168 | 4140 | scope, |
| 4169 | parent_src, | |
| 4170 | d, | |
| 4141 | try self.srcLocInfo(file, pl_node.src_node, parent_src), | |
| 4142 | extra.data, | |
| 4143 | @intCast(extra.end), | |
| 4171 | 4144 | ); |
| 4172 | 4145 | } |
| 4173 | 4146 | |
| 4174 | 4147 | return it.extra_index; |
| 4175 | 4148 | } |
| 4176 | 4149 | |
| 4150 | fn 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 | 4181 | // Asserts the given decl is public |
| 4178 | 4182 | fn analyzeDecl( |
| 4179 | 4183 | self: *Autodoc, |
| 4180 | 4184 | file: *File, |
| 4181 | 4185 | scope: *Scope, |
| 4182 | parent_src: SrcLocInfo, | |
| 4186 | decl_src: SrcLocInfo, | |
| 4183 | 4187 | decl_indexes: *std.ArrayListUnmanaged(usize), |
| 4184 | 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 | 4192 | call_ctx: ?*const CallContext, |
| 4187 | 4193 | ) AutodocErrors!void { |
| 4188 | const data = file.zir.instructions.items(.data); | |
| 4189 | const is_pub = @as(u1, @truncate(d.flags >> 0)) != 0; | |
| 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; | |
| 4194 | const bodies = declaration.getBodies(extra_index, file.zir); | |
| 4195 | const name = file.zir.nullTerminatedString(declaration.name.toString(file.zir).?); | |
| 4223 | 4196 | |
| 4224 | const addrspace_inst: Zir.Inst.Ref = if (!has_section_or_addrspace) .none else inst: { | |
| 4225 | const inst: Zir.Inst.Ref = @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) | |
| 4197 | const doc_comment: ?[]const u8 = if (declaration.flags.has_doc_comment) | |
| 4198 | file.zir.nullTerminatedString(@enumFromInt(file.zir.extra[extra_index])) | |
| 4248 | 4199 | else |
| 4249 | 4200 | null; |
| 4250 | 4201 | |
| ... | ... | @@ -4261,16 +4212,22 @@ fn analyzeDecl( |
| 4261 | 4212 | break :idx idx; |
| 4262 | 4213 | }; |
| 4263 | 4214 | |
| 4264 | const walk_result = try self.walkInstruction( | |
| 4215 | const walk_result = try self.walkInlineBody( | |
| 4265 | 4216 | file, |
| 4266 | 4217 | scope, |
| 4267 | 4218 | decl_src, |
| 4268 | value_index, | |
| 4219 | decl_src, | |
| 4220 | bodies.value_body, | |
| 4269 | 4221 | true, |
| 4270 | 4222 | call_ctx, |
| 4271 | 4223 | ); |
| 4272 | 4224 | |
| 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 | }; | |
| 4274 | 4231 | |
| 4275 | 4232 | const decls_slot_index = self.decls.items.len; |
| 4276 | 4233 | try self.decls.append(self.arena, .{ |
| ... | ... | @@ -4281,13 +4238,13 @@ fn analyzeDecl( |
| 4281 | 4238 | .parent_container = scope.enclosing_type, |
| 4282 | 4239 | }); |
| 4283 | 4240 | |
| 4284 | if (is_pub) { | |
| 4241 | if (declaration.flags.is_pub) { | |
| 4285 | 4242 | try decl_indexes.append(self.arena, decls_slot_index); |
| 4286 | 4243 | } else { |
| 4287 | 4244 | try priv_decl_indexes.append(self.arena, decls_slot_index); |
| 4288 | 4245 | } |
| 4289 | 4246 | |
| 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 | 4248 | std.debug.assert(decl_status_ptr.* == .Pending); |
| 4292 | 4249 | decl_status_ptr.* = .{ .Analyzed = decls_slot_index }; |
| 4293 | 4250 | |
| ... | ... | @@ -4296,7 +4253,7 @@ fn analyzeDecl( |
| 4296 | 4253 | for (paths.items) |resume_info| { |
| 4297 | 4254 | try self.tryResolveRefPath( |
| 4298 | 4255 | resume_info.file, |
| 4299 | value_index, | |
| 4256 | decl_inst, | |
| 4300 | 4257 | resume_info.ref_path, |
| 4301 | 4258 | ); |
| 4302 | 4259 | } |
| ... | ... | @@ -4312,24 +4269,17 @@ fn analyzeUsingnamespaceDecl( |
| 4312 | 4269 | self: *Autodoc, |
| 4313 | 4270 | file: *File, |
| 4314 | 4271 | scope: *Scope, |
| 4315 | parent_src: SrcLocInfo, | |
| 4272 | decl_src: SrcLocInfo, | |
| 4316 | 4273 | decl_indexes: *std.ArrayListUnmanaged(usize), |
| 4317 | 4274 | priv_decl_indexes: *std.ArrayListUnmanaged(usize), |
| 4318 | d: Zir.DeclIterator.Item, | |
| 4275 | declaration: Zir.Inst.Declaration, | |
| 4276 | extra_index: u32, | |
| 4319 | 4277 | call_ctx: ?*const CallContext, |
| 4320 | 4278 | ) AutodocErrors!void { |
| 4321 | const data = file.zir.instructions.items(.data); | |
| 4279 | const bodies = declaration.getBodies(extra_index, file.zir); | |
| 4322 | 4280 | |
| 4323 | const is_pub = @as(u1, @truncate(d.flags)) != 0; | |
| 4324 | const value_index: Zir.Inst.Index = @enumFromInt(file.zir.extra[@intFromEnum(d.sub_index) + 6]); | |
| 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) | |
| 4281 | const doc_comment: ?[]const u8 = if (declaration.flags.has_doc_comment) | |
| 4282 | file.zir.nullTerminatedString(@enumFromInt(file.zir.extra[extra_index])) | |
| 4333 | 4283 | else |
| 4334 | 4284 | null; |
| 4335 | 4285 | |
| ... | ... | @@ -4346,11 +4296,12 @@ fn analyzeUsingnamespaceDecl( |
| 4346 | 4296 | break :idx idx; |
| 4347 | 4297 | }; |
| 4348 | 4298 | |
| 4349 | const walk_result = try self.walkInstruction( | |
| 4299 | const walk_result = try self.walkInlineBody( | |
| 4350 | 4300 | file, |
| 4351 | 4301 | scope, |
| 4352 | 4302 | decl_src, |
| 4353 | value_index, | |
| 4303 | decl_src, | |
| 4304 | bodies.value_body, | |
| 4354 | 4305 | true, |
| 4355 | 4306 | call_ctx, |
| 4356 | 4307 | ); |
| ... | ... | @@ -4365,7 +4316,7 @@ fn analyzeUsingnamespaceDecl( |
| 4365 | 4316 | .parent_container = scope.enclosing_type, |
| 4366 | 4317 | }); |
| 4367 | 4318 | |
| 4368 | if (is_pub) { | |
| 4319 | if (declaration.flags.is_pub) { | |
| 4369 | 4320 | try decl_indexes.append(self.arena, decl_slot_index); |
| 4370 | 4321 | } else { |
| 4371 | 4322 | try priv_decl_indexes.append(self.arena, decl_slot_index); |
| ... | ... | @@ -4376,18 +4327,14 @@ fn analyzeDecltest( |
| 4376 | 4327 | self: *Autodoc, |
| 4377 | 4328 | file: *File, |
| 4378 | 4329 | scope: *Scope, |
| 4379 | parent_src: SrcLocInfo, | |
| 4380 | d: Zir.DeclIterator.Item, | |
| 4330 | decl_src: SrcLocInfo, | |
| 4331 | declaration: Zir.Inst.Declaration, | |
| 4332 | extra_index: u32, | |
| 4381 | 4333 | ) AutodocErrors!void { |
| 4382 | const data = file.zir.instructions.items(.data); | |
| 4383 | ||
| 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); | |
| 4334 | std.debug.assert(declaration.flags.has_doc_comment); | |
| 4335 | const decl_name_index: Zir.NullTerminatedString = @enumFromInt(file.zir.extra[extra_index]); | |
| 4389 | 4336 | |
| 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); | |
| 4391 | 4338 | |
| 4392 | 4339 | const decl_name: ?[]const u8 = if (decl_name_index != .empty) |
| 4393 | 4340 | file.zir.nullTerminatedString(decl_name_index) |
| ... | ... | @@ -5830,17 +5777,6 @@ fn walkRef( |
| 5830 | 5777 | } |
| 5831 | 5778 | } |
| 5832 | 5779 | |
| 5833 | fn 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 | ||
| 5844 | 5780 | fn printWithContext( |
| 5845 | 5781 | file: *File, |
| 5846 | 5782 | inst: Zir.Inst.Index, |
src/Compilation.zig+4-1| ... | ... | @@ -2802,6 +2802,7 @@ const Header = extern struct { |
| 2802 | 2802 | extra_len: u32, |
| 2803 | 2803 | limbs_len: u32, |
| 2804 | 2804 | string_bytes_len: u32, |
| 2805 | tracked_insts_len: u32, | |
| 2805 | 2806 | }, |
| 2806 | 2807 | }; |
| 2807 | 2808 | |
| ... | ... | @@ -2809,7 +2810,7 @@ const Header = extern struct { |
| 2809 | 2810 | /// saved, such as the target and most CLI flags. A cache hit will only occur |
| 2810 | 2811 | /// when subsequent compiler invocations use the same set of flags. |
| 2811 | 2812 | pub 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 | 2814 | var bufs_len: usize = 0; |
| 2814 | 2815 | |
| 2815 | 2816 | const lf = comp.bin_file orelse return; |
| ... | ... | @@ -2822,6 +2823,7 @@ pub fn saveState(comp: *Compilation) !void { |
| 2822 | 2823 | .extra_len = @intCast(ip.extra.items.len), |
| 2823 | 2824 | .limbs_len = @intCast(ip.limbs.items.len), |
| 2824 | 2825 | .string_bytes_len = @intCast(ip.string_bytes.items.len), |
| 2826 | .tracked_insts_len = @intCast(ip.tracked_insts.count()), | |
| 2825 | 2827 | }, |
| 2826 | 2828 | }; |
| 2827 | 2829 | addBuf(&bufs_list, &bufs_len, mem.asBytes(&header)); |
| ... | ... | @@ -2830,6 +2832,7 @@ pub fn saveState(comp: *Compilation) !void { |
| 2830 | 2832 | addBuf(&bufs_list, &bufs_len, mem.sliceAsBytes(ip.items.items(.data))); |
| 2831 | 2833 | addBuf(&bufs_list, &bufs_len, mem.sliceAsBytes(ip.items.items(.tag))); |
| 2832 | 2834 | addBuf(&bufs_list, &bufs_len, ip.string_bytes.items); |
| 2835 | addBuf(&bufs_list, &bufs_len, mem.sliceAsBytes(ip.tracked_insts.keys())); | |
| 2833 | 2836 | |
| 2834 | 2837 | // TODO: compilation errors |
| 2835 | 2838 | // TODO: files |
src/InternPool.zig+51-21| ... | ... | @@ -54,6 +54,34 @@ string_table: std.HashMapUnmanaged( |
| 54 | 54 | std.hash_map.default_max_load_percentage, |
| 55 | 55 | ) = .{}, |
| 56 | 56 | |
| 57 | /// An index into `tracked_insts` gives a reference to a single ZIR instruction which | |
| 58 | /// persists across incremental updates. | |
| 59 | tracked_insts: std.AutoArrayHashMapUnmanaged(TrackedInst, void) = .{}, | |
| 60 | ||
| 61 | pub 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 | ||
| 76 | pub 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 | ||
| 57 | 85 | const FieldMap = std.ArrayHashMapUnmanaged(void, void, std.array_hash_map.AutoContext(void), false); |
| 58 | 86 | |
| 59 | 87 | const builtin = @import("builtin"); |
| ... | ... | @@ -62,11 +90,13 @@ const Allocator = std.mem.Allocator; |
| 62 | 90 | const assert = std.debug.assert; |
| 63 | 91 | const BigIntConst = std.math.big.int.Const; |
| 64 | 92 | const BigIntMutable = std.math.big.int.Mutable; |
| 93 | const Cache = std.Build.Cache; | |
| 65 | 94 | const Limb = std.math.big.Limb; |
| 66 | 95 | const Hash = std.hash.Wyhash; |
| 67 | 96 | |
| 68 | 97 | const InternPool = @This(); |
| 69 | 98 | const Module = @import("Module.zig"); |
| 99 | const Zcu = Module; | |
| 70 | 100 | const Zir = @import("Zir.zig"); |
| 71 | 101 | |
| 72 | 102 | const KeyAdapter = struct { |
| ... | ... | @@ -409,7 +439,7 @@ pub const Key = union(enum) { |
| 409 | 439 | /// `none` when the struct has no declarations. |
| 410 | 440 | namespace: OptionalNamespaceIndex, |
| 411 | 441 | /// Index of the struct_decl ZIR instruction. |
| 412 | zir_index: Zir.Inst.Index, | |
| 442 | zir_index: TrackedInst.Index, | |
| 413 | 443 | layout: std.builtin.Type.ContainerLayout, |
| 414 | 444 | field_names: NullTerminatedString.Slice, |
| 415 | 445 | field_types: Index.Slice, |
| ... | ... | @@ -653,7 +683,7 @@ pub const Key = union(enum) { |
| 653 | 683 | } |
| 654 | 684 | |
| 655 | 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 | 687 | assert(s.layout != .Packed); |
| 658 | 688 | const field_index = std.meta.fieldIndex(Tag.TypeStruct, "zir_index").?; |
| 659 | 689 | ip.extra.items[s.extra_index + field_index] = @intFromEnum(new_zir_index); |
| ... | ... | @@ -769,7 +799,7 @@ pub const Key = union(enum) { |
| 769 | 799 | flags: Tag.TypeUnion.Flags, |
| 770 | 800 | /// The enum that provides the list of field names and values. |
| 771 | 801 | enum_tag_ty: Index, |
| 772 | zir_index: Zir.Inst.Index, | |
| 802 | zir_index: TrackedInst.Index, | |
| 773 | 803 | |
| 774 | 804 | /// The returned pointer expires with any addition to the `InternPool`. |
| 775 | 805 | pub fn flagsPtr(self: @This(), ip: *const InternPool) *Tag.TypeUnion.Flags { |
| ... | ... | @@ -1056,7 +1086,7 @@ pub const Key = union(enum) { |
| 1056 | 1086 | /// the body. We store this rather than the body directly so that when ZIR |
| 1057 | 1087 | /// is regenerated on update(), we can map this to the new corresponding |
| 1058 | 1088 | /// ZIR instruction. |
| 1059 | zir_body_inst: Zir.Inst.Index, | |
| 1089 | zir_body_inst: TrackedInst.Index, | |
| 1060 | 1090 | /// Relative to owner Decl. |
| 1061 | 1091 | lbrace_line: u32, |
| 1062 | 1092 | /// Relative to owner Decl. |
| ... | ... | @@ -1082,7 +1112,7 @@ pub const Key = union(enum) { |
| 1082 | 1112 | } |
| 1083 | 1113 | |
| 1084 | 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 | 1116 | return @ptrCast(&ip.extra.items[func.zir_body_inst_extra_index]); |
| 1087 | 1117 | } |
| 1088 | 1118 | |
| ... | ... | @@ -1860,7 +1890,7 @@ pub const UnionType = struct { |
| 1860 | 1890 | /// If this slice has length 0 it means all elements are `none`. |
| 1861 | 1891 | field_aligns: Alignment.Slice, |
| 1862 | 1892 | /// Index of the union_decl ZIR instruction. |
| 1863 | zir_index: Zir.Inst.Index, | |
| 1893 | zir_index: TrackedInst.Index, | |
| 1864 | 1894 | /// Index into extra array of the `flags` field. |
| 1865 | 1895 | flags_index: u32, |
| 1866 | 1896 | /// Copied from `enum_tag_ty`. |
| ... | ... | @@ -1954,10 +1984,10 @@ pub const UnionType = struct { |
| 1954 | 1984 | } |
| 1955 | 1985 | |
| 1956 | 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 | 1988 | const flags_field_index = std.meta.fieldIndex(Tag.TypeUnion, "flags").?; |
| 1959 | 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 | 1991 | @ptrCast(&ip.extra.items[self.flags_index - flags_field_index + zir_index_field_index]); |
| 1962 | 1992 | ptr.* = new_zir_index; |
| 1963 | 1993 | } |
| ... | ... | @@ -2976,7 +3006,7 @@ pub const Tag = enum(u8) { |
| 2976 | 3006 | analysis: FuncAnalysis, |
| 2977 | 3007 | owner_decl: DeclIndex, |
| 2978 | 3008 | ty: Index, |
| 2979 | zir_body_inst: Zir.Inst.Index, | |
| 3009 | zir_body_inst: TrackedInst.Index, | |
| 2980 | 3010 | lbrace_line: u32, |
| 2981 | 3011 | rbrace_line: u32, |
| 2982 | 3012 | lbrace_column: u32, |
| ... | ... | @@ -3050,7 +3080,7 @@ pub const Tag = enum(u8) { |
| 3050 | 3080 | namespace: NamespaceIndex, |
| 3051 | 3081 | /// The enum that provides the list of field names and values. |
| 3052 | 3082 | tag_ty: Index, |
| 3053 | zir_index: Zir.Inst.Index, | |
| 3083 | zir_index: TrackedInst.Index, | |
| 3054 | 3084 | |
| 3055 | 3085 | pub const Flags = packed struct(u32) { |
| 3056 | 3086 | runtime_tag: UnionType.RuntimeTag, |
| ... | ... | @@ -3072,7 +3102,7 @@ pub const Tag = enum(u8) { |
| 3072 | 3102 | /// 2. init: Index for each fields_len // if tag is type_struct_packed_inits |
| 3073 | 3103 | pub const TypeStructPacked = struct { |
| 3074 | 3104 | decl: DeclIndex, |
| 3075 | zir_index: Zir.Inst.Index, | |
| 3105 | zir_index: TrackedInst.Index, | |
| 3076 | 3106 | fields_len: u32, |
| 3077 | 3107 | namespace: OptionalNamespaceIndex, |
| 3078 | 3108 | backing_int_ty: Index, |
| ... | ... | @@ -3119,7 +3149,7 @@ pub const Tag = enum(u8) { |
| 3119 | 3149 | /// 7. field_offset: u32 // for each field in declared order, undef until layout_resolved |
| 3120 | 3150 | pub const TypeStruct = struct { |
| 3121 | 3151 | decl: DeclIndex, |
| 3122 | zir_index: Zir.Inst.Index, | |
| 3152 | zir_index: TrackedInst.Index, | |
| 3123 | 3153 | fields_len: u32, |
| 3124 | 3154 | flags: Flags, |
| 3125 | 3155 | size: u32, |
| ... | ... | @@ -3708,6 +3738,8 @@ pub fn deinit(ip: *InternPool, gpa: Allocator) void { |
| 3708 | 3738 | |
| 3709 | 3739 | ip.string_table.deinit(gpa); |
| 3710 | 3740 | |
| 3741 | ip.tracked_insts.deinit(gpa); | |
| 3742 | ||
| 3711 | 3743 | ip.* = undefined; |
| 3712 | 3744 | } |
| 3713 | 3745 | |
| ... | ... | @@ -5358,7 +5390,7 @@ pub const UnionTypeInit = struct { |
| 5358 | 5390 | flags: Tag.TypeUnion.Flags, |
| 5359 | 5391 | decl: DeclIndex, |
| 5360 | 5392 | namespace: NamespaceIndex, |
| 5361 | zir_index: Zir.Inst.Index, | |
| 5393 | zir_index: TrackedInst.Index, | |
| 5362 | 5394 | fields_len: u32, |
| 5363 | 5395 | enum_tag_ty: Index, |
| 5364 | 5396 | /// May have length 0 which leaves the values unset until later. |
| ... | ... | @@ -5430,7 +5462,7 @@ pub const StructTypeInit = struct { |
| 5430 | 5462 | decl: DeclIndex, |
| 5431 | 5463 | namespace: OptionalNamespaceIndex, |
| 5432 | 5464 | layout: std.builtin.Type.ContainerLayout, |
| 5433 | zir_index: Zir.Inst.Index, | |
| 5465 | zir_index: TrackedInst.Index, | |
| 5434 | 5466 | fields_len: u32, |
| 5435 | 5467 | known_non_opv: bool, |
| 5436 | 5468 | requires_comptime: RequiresComptime, |
| ... | ... | @@ -5704,7 +5736,7 @@ pub fn getExternFunc(ip: *InternPool, gpa: Allocator, key: Key.ExternFunc) Alloc |
| 5704 | 5736 | pub const GetFuncDeclKey = struct { |
| 5705 | 5737 | owner_decl: DeclIndex, |
| 5706 | 5738 | ty: Index, |
| 5707 | zir_body_inst: Zir.Inst.Index, | |
| 5739 | zir_body_inst: TrackedInst.Index, | |
| 5708 | 5740 | lbrace_line: u32, |
| 5709 | 5741 | rbrace_line: u32, |
| 5710 | 5742 | lbrace_column: u32, |
| ... | ... | @@ -5773,7 +5805,7 @@ pub const GetFuncDeclIesKey = struct { |
| 5773 | 5805 | is_var_args: bool, |
| 5774 | 5806 | is_generic: bool, |
| 5775 | 5807 | is_noinline: bool, |
| 5776 | zir_body_inst: Zir.Inst.Index, | |
| 5808 | zir_body_inst: TrackedInst.Index, | |
| 5777 | 5809 | lbrace_line: u32, |
| 5778 | 5810 | rbrace_line: u32, |
| 5779 | 5811 | lbrace_column: u32, |
| ... | ... | @@ -6186,8 +6218,6 @@ fn finishFuncInstance( |
| 6186 | 6218 | .generation = generation, |
| 6187 | 6219 | .is_pub = fn_owner_decl.is_pub, |
| 6188 | 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 | 6221 | .alive = true, |
| 6192 | 6222 | .kind = .anon, |
| 6193 | 6223 | }); |
| ... | ... | @@ -6537,7 +6567,7 @@ fn addExtraAssumeCapacity(ip: *InternPool, extra: anytype) u32 { |
| 6537 | 6567 | NullTerminatedString, |
| 6538 | 6568 | OptionalNullTerminatedString, |
| 6539 | 6569 | Tag.TypePointer.VectorIndex, |
| 6540 | Zir.Inst.Index, | |
| 6570 | TrackedInst.Index, | |
| 6541 | 6571 | => @intFromEnum(@field(extra, field.name)), |
| 6542 | 6572 | |
| 6543 | 6573 | u32, |
| ... | ... | @@ -6613,7 +6643,7 @@ fn extraDataTrail(ip: *const InternPool, comptime T: type, index: usize) struct |
| 6613 | 6643 | NullTerminatedString, |
| 6614 | 6644 | OptionalNullTerminatedString, |
| 6615 | 6645 | Tag.TypePointer.VectorIndex, |
| 6616 | Zir.Inst.Index, | |
| 6646 | TrackedInst.Index, | |
| 6617 | 6647 | => @enumFromInt(int32), |
| 6618 | 6648 | |
| 6619 | 6649 | u32, |
| ... | ... | @@ -8319,7 +8349,7 @@ pub fn funcHasInferredErrorSet(ip: *const InternPool, i: Index) bool { |
| 8319 | 8349 | return funcAnalysis(ip, i).inferred_error_set; |
| 8320 | 8350 | } |
| 8321 | 8351 | |
| 8322 | pub fn funcZirBodyInst(ip: *const InternPool, i: Index) Zir.Inst.Index { | |
| 8352 | pub fn funcZirBodyInst(ip: *const InternPool, i: Index) TrackedInst.Index { | |
| 8323 | 8353 | assert(i != .none); |
| 8324 | 8354 | const item = ip.items.get(@intFromEnum(i)); |
| 8325 | 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 | 386 | /// do not need to be loaded into memory in order to compute debug line numbers. |
| 387 | 387 | /// This value is absolute. |
| 388 | 388 | src_line: u32, |
| 389 | /// Index to ZIR `extra` array to the entry in the parent's decl structure | |
| 390 | /// (the part that says "for every decls_len"). The first item at this index is | |
| 391 | /// the contents hash, followed by line, name, etc. | |
| 392 | /// For anonymous decls and also the root Decl for a File, this is `none`. | |
| 393 | zir_decl_index: Zir.OptionalExtraIndex, | |
| 389 | /// Index of the ZIR `declaration` instruction from which this `Decl` was created. | |
| 390 | /// For the root `Decl` of a `File` and legacy anonymous decls, this is `.none`. | |
| 391 | zir_decl_index: Zir.Inst.OptionalIndex, | |
| 394 | 392 | |
| 395 | 393 | /// Represents the "shallow" analysis status. For example, for decls that are functions, |
| 396 | 394 | /// the function type is analyzed with this set to `in_progress`, however, the semantic |
| ... | ... | @@ -442,10 +440,6 @@ pub const Decl = struct { |
| 442 | 440 | is_pub: bool, |
| 443 | 441 | /// Whether the corresponding AST decl has a `export` keyword. |
| 444 | 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 | 443 | /// Flag used by garbage collection to mark and sweep. |
| 450 | 444 | /// Decls which correspond to an AST node always have this field set to `true`. |
| 451 | 445 | /// Anonymous Decls are initialized with this field set to `false` and then it |
| ... | ... | @@ -471,81 +465,19 @@ pub const Decl = struct { |
| 471 | 465 | const Index = InternPool.DeclIndex; |
| 472 | 466 | const OptionalIndex = InternPool.OptionalDeclIndex; |
| 473 | 467 | |
| 474 | pub const DepsTable = std.AutoArrayHashMapUnmanaged(Decl.Index, DepType); | |
| 475 | ||
| 476 | /// Later types take priority; e.g. if a dependent decl has both `normal` | |
| 477 | /// and `function_body` dependencies on another decl, it will be marked as | |
| 478 | /// having a `function_body` dependency. | |
| 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); | |
| 468 | /// Asserts that `zir_decl_index` is not `.none`. | |
| 469 | fn getDeclaration(decl: Decl, zir: Zir) Zir.Inst.Declaration { | |
| 470 | const zir_index = decl.zir_decl_index.unwrap().?; | |
| 471 | const pl_node = zir.instructions.items(.data)[@intFromEnum(zir_index)].pl_node; | |
| 472 | return zir.extraData(Zir.Inst.Declaration, pl_node.payload_index).data; | |
| 504 | 473 | } |
| 505 | 474 | |
| 506 | pub fn contentsHash(decl: Decl, mod: *Module) std.zig.SrcHash { | |
| 507 | const zir = decl.getFileScope(mod).zir; | |
| 508 | return decl.contentsHashZir(zir); | |
| 509 | } | |
| 510 | ||
| 511 | pub fn contentsHashZir(decl: Decl, zir: Zir) std.zig.SrcHash { | |
| 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; | |
| 475 | pub fn zirBodies(decl: Decl, zcu: *Zcu) Zir.Inst.Declaration.Bodies { | |
| 476 | const zir = decl.getFileScope(zcu).zir; | |
| 477 | const zir_index = decl.zir_decl_index.unwrap().?; | |
| 478 | const pl_node = zir.instructions.items(.data)[@intFromEnum(zir_index)].pl_node; | |
| 479 | const extra = zir.extraData(Zir.Inst.Declaration, pl_node.payload_index); | |
| 480 | return extra.data.getBodies(@intCast(extra.end), zir); | |
| 549 | 481 | } |
| 550 | 482 | |
| 551 | 483 | pub fn relativeToNodeIndex(decl: Decl, offset: i32) Ast.Node.Index { |
| ... | ... | @@ -902,6 +834,9 @@ pub const File = struct { |
| 902 | 834 | multi_pkg: bool = false, |
| 903 | 835 | /// List of references to this file, used for multi-package errors. |
| 904 | 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, | |
| 905 | 840 | |
| 906 | 841 | /// Used by change detection algorithm, after astgen, contains the |
| 907 | 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 | 2597 | const stat = try source_file.stat(); |
| 2663 | 2598 | |
| 2664 | 2599 | const want_local_cache = file.mod == mod.main_mod; |
| 2665 | const digest = hash: { | |
| 2600 | const bin_digest = hash: { | |
| 2666 | 2601 | var path_hash: Cache.HashHelper = .{}; |
| 2667 | 2602 | path_hash.addBytes(build_options.version); |
| 2668 | 2603 | path_hash.add(builtin.zig_backend); |
| ... | ... | @@ -2671,7 +2606,19 @@ pub fn astGenFile(mod: *Module, file: *File) !void { |
| 2671 | 2606 | path_hash.addBytes(file.mod.root.sub_path); |
| 2672 | 2607 | } |
| 2673 | 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 | 2623 | const cache_directory = if (want_local_cache) mod.local_zir_cache else mod.global_zir_cache; |
| 2677 | 2624 | const zir_dir = cache_directory.handle; |
| ... | ... | @@ -2681,7 +2628,7 @@ pub fn astGenFile(mod: *Module, file: *File) !void { |
| 2681 | 2628 | .never_loaded, .retryable_failure => lock: { |
| 2682 | 2629 | // First, load the cached ZIR code, if any. |
| 2683 | 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 | }); |
| 2686 | 2633 | |
| 2687 | 2634 | break :lock .shared; |
| ... | ... | @@ -2708,7 +2655,7 @@ pub fn astGenFile(mod: *Module, file: *File) !void { |
| 2708 | 2655 | // version. Likewise if we're working on AstGen and another process asks for |
| 2709 | 2656 | // the cached file, they'll get it. |
| 2710 | 2657 | const cache_file = while (true) { |
| 2711 | break zir_dir.createFile(&digest, .{ | |
| 2658 | break zir_dir.createFile(&hex_digest, .{ | |
| 2712 | 2659 | .read = true, |
| 2713 | 2660 | .truncate = false, |
| 2714 | 2661 | .lock = lock, |
| ... | ... | @@ -2894,7 +2841,7 @@ pub fn astGenFile(mod: *Module, file: *File) !void { |
| 2894 | 2841 | }; |
| 2895 | 2842 | cache_file.writevAll(&iovecs) catch |err| { |
| 2896 | 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 | }; |
| 2900 | 2847 | |
| ... | ... | @@ -3003,93 +2950,22 @@ fn loadZirCacheBody(gpa: Allocator, header: Zir.Header, cache_file: std.fs.File) |
| 3003 | 2950 | return zir; |
| 3004 | 2951 | } |
| 3005 | 2952 | |
| 3006 | /// Patch ups: | |
| 3007 | /// * Struct.zir_index | |
| 3008 | /// * Decl.zir_index | |
| 3009 | /// * Fn.zir_body_inst | |
| 3010 | /// * Decl.zir_decl_index | |
| 3011 | fn 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; | |
| 2953 | fn updateZirRefs(zcu: *Module, file: *File, old_zir: Zir) !void { | |
| 2954 | const gpa = zcu.gpa; | |
| 3017 | 2955 | |
| 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 | 2956 | var inst_map: std.AutoHashMapUnmanaged(Zir.Inst.Index, Zir.Inst.Index) = .{}; |
| 3021 | 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(); | |
| 3039 | 2958 | |
| 3040 | // The root decl is always outdated; otherwise we would not have had | |
| 3041 | // to re-generate ZIR for the File. | |
| 3042 | try file.outdated_decls.append(gpa, root_decl); | |
| 2959 | try mapOldZirToNew(gpa, old_zir, file.zir, &inst_map); | |
| 3043 | 2960 | |
| 3044 | const ip = &mod.intern_pool; | |
| 3045 | ||
| 3046 | while (decl_stack.popOrNull()) |decl_index| { | |
| 3047 | const decl = mod.declPtr(decl_index); | |
| 3048 | // Anonymous decls and the root decl have this set to 0. We still need | |
| 3049 | // to walk them but we do not need to modify this value. | |
| 3050 | // Anonymous decls should not be marked outdated. They will be re-generated | |
| 3051 | // if their owner decl is marked outdated. | |
| 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 | } | |
| 2961 | // TODO: this should be done after all AstGen workers complete, to avoid | |
| 2962 | // iterating over this full set for every updated file. | |
| 2963 | for (zcu.intern_pool.tracked_insts.keys()) |*ti| { | |
| 2964 | if (!std.mem.eql(u8, &ti.path_digest, &file.path_digest)) continue; | |
| 2965 | ti.inst = inst_map.get(ti.inst) orelse { | |
| 2966 | // TODO: invalidate this `TrackedInst` via the dependency mechanism | |
| 2967 | continue; | |
| 2968 | }; | |
| 3093 | 2969 | } |
| 3094 | 2970 | } |
| 3095 | 2971 | |
| ... | ... | @@ -3098,9 +2974,9 @@ pub fn mapOldZirToNew( |
| 3098 | 2974 | old_zir: Zir, |
| 3099 | 2975 | new_zir: Zir, |
| 3100 | 2976 | inst_map: *std.AutoHashMapUnmanaged(Zir.Inst.Index, Zir.Inst.Index), |
| 3101 | extra_map: *std.AutoHashMapUnmanaged(Zir.ExtraIndex, Zir.ExtraIndex), | |
| 3102 | 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 | 2980 | const MatchedZirDecl = struct { |
| 3105 | 2981 | old_inst: Zir.Inst.Index, |
| 3106 | 2982 | new_inst: Zir.Inst.Index, |
| ... | ... | @@ -3108,47 +2984,113 @@ pub fn mapOldZirToNew( |
| 3108 | 2984 | var match_stack: ArrayListUnmanaged(MatchedZirDecl) = .{}; |
| 3109 | 2985 | defer match_stack.deinit(gpa); |
| 3110 | 2986 | |
| 3111 | // Main struct inst is always the same | |
| 2987 | // Main struct inst is always matched | |
| 3112 | 2988 | try match_stack.append(gpa, .{ |
| 3113 | 2989 | .old_inst = .main_struct_inst, |
| 3114 | 2990 | .new_inst = .main_struct_inst, |
| 3115 | 2991 | }); |
| 3116 | 2992 | |
| 2993 | // Used as temporary buffers for namespace declaration instructions | |
| 3117 | 2994 | var old_decls = std.ArrayList(Zir.Inst.Index).init(gpa); |
| 3118 | 2995 | defer old_decls.deinit(); |
| 3119 | 2996 | var new_decls = std.ArrayList(Zir.Inst.Index).init(gpa); |
| 3120 | 2997 | defer new_decls.deinit(); |
| 3121 | 2998 | |
| 3122 | 2999 | while (match_stack.popOrNull()) |match_item| { |
| 3000 | // Match the namespace declaration itself | |
| 3123 | 3001 | try inst_map.put(gpa, match_item.old_inst, match_item.new_inst); |
| 3124 | 3002 | |
| 3125 | // Maps name to extra index of decl sub item. | |
| 3126 | var decl_map: std.StringHashMapUnmanaged(Zir.ExtraIndex) = .{}; | |
| 3127 | defer decl_map.deinit(gpa); | |
| 3003 | // Maps decl name to `declaration` instruction. | |
| 3004 | var named_decls: std.StringHashMapUnmanaged(Zir.Inst.Index) = .{}; | |
| 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); | |
| 3128 | 3018 | |
| 3129 | 3019 | { |
| 3130 | 3020 | var old_decl_it = old_zir.declIterator(match_item.old_inst); |
| 3131 | while (old_decl_it.next()) |old_decl| { | |
| 3132 | try decl_map.put(gpa, old_decl.name, old_decl.sub_index); | |
| 3021 | while (old_decl_it.next()) |old_decl_inst| { | |
| 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 | } |
| 3135 | 3039 | |
| 3040 | var unnamed_test_idx: u32 = 0; | |
| 3041 | var comptime_decl_idx: u32 = 0; | |
| 3042 | var usingnamespace_decl_idx: u32 = 0; | |
| 3043 | ||
| 3136 | 3044 | var new_decl_it = new_zir.declIterator(match_item.new_inst); |
| 3137 | while (new_decl_it.next()) |new_decl| { | |
| 3138 | const old_extra_index = decl_map.get(new_decl.name) orelse continue; | |
| 3139 | const new_extra_index = new_decl.sub_index; | |
| 3140 | try extra_map.put(gpa, old_extra_index, new_extra_index); | |
| 3141 | ||
| 3142 | try old_zir.findDecls(&old_decls, old_extra_index); | |
| 3143 | try new_zir.findDecls(&new_decls, new_extra_index); | |
| 3144 | var i: usize = 0; | |
| 3145 | while (true) : (i += 1) { | |
| 3146 | if (i >= old_decls.items.len) break; | |
| 3147 | if (i >= new_decls.items.len) break; | |
| 3148 | try match_stack.append(gpa, .{ | |
| 3149 | .old_inst = old_decls.items[i], | |
| 3150 | .new_inst = new_decls.items[i], | |
| 3151 | }); | |
| 3045 | while (new_decl_it.next()) |new_decl_inst| { | |
| 3046 | const new_decl, _ = new_zir.getDeclaration(new_decl_inst); | |
| 3047 | // Attempt to match this to a declaration in the old ZIR: | |
| 3048 | // * For named declarations (`const`/`var`/`fn`), we match based on name. | |
| 3049 | // * For named tests (`test "foo"`), we also match based on name. | |
| 3050 | // * For unnamed tests and decltests, we match based on order. | |
| 3051 | // * For comptime blocks, we match based on order. | |
| 3052 | // * For usingnamespace decls, we match based on order. | |
| 3053 | // If we cannot match this declaration, we can't match anything nested inside of it either, so we just `continue`. | |
| 3054 | const old_decl_inst = switch (new_decl.name) { | |
| 3055 | .@"comptime" => inst: { | |
| 3056 | if (comptime_decl_idx == comptime_decls.items.len) continue; | |
| 3057 | defer comptime_decl_idx += 1; | |
| 3058 | break :inst comptime_decls.items[comptime_decl_idx]; | |
| 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 | 3399 | new_decl.src_line = 0; |
| 3458 | 3400 | new_decl.is_pub = true; |
| 3459 | 3401 | new_decl.is_exported = false; |
| 3460 | new_decl.has_align = false; | |
| 3461 | new_decl.has_linksection_or_addrspace = false; | |
| 3462 | 3402 | new_decl.ty = Type.type; |
| 3463 | 3403 | new_decl.alignment = .none; |
| 3464 | 3404 | new_decl.@"linksection" = .none; |
| ... | ... | @@ -3502,7 +3442,7 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void { |
| 3502 | 3442 | const struct_ty = sema.getStructType( |
| 3503 | 3443 | new_decl_index, |
| 3504 | 3444 | new_namespace_index, |
| 3505 | .main_struct_inst, | |
| 3445 | try mod.intern_pool.trackZir(gpa, file, .main_struct_inst), | |
| 3506 | 3446 | ) catch |err| switch (err) { |
| 3507 | 3447 | error.OutOfMemory => return error.OutOfMemory, |
| 3508 | 3448 | }; |
| ... | ... | @@ -3561,7 +3501,6 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { |
| 3561 | 3501 | |
| 3562 | 3502 | const gpa = mod.gpa; |
| 3563 | 3503 | const zir = decl.getFileScope(mod).zir; |
| 3564 | const zir_datas = zir.instructions.items(.data); | |
| 3565 | 3504 | |
| 3566 | 3505 | const builtin_type_target_index: InternPool.Index = blk: { |
| 3567 | 3506 | const std_mod = mod.std_mod; |
| ... | ... | @@ -3639,11 +3578,9 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { |
| 3639 | 3578 | }; |
| 3640 | 3579 | defer block_scope.instructions.deinit(gpa); |
| 3641 | 3580 | |
| 3642 | const zir_block_index = decl.zirBlockIndex(mod); | |
| 3643 | const inst_data = zir_datas[@intFromEnum(zir_block_index)].pl_node; | |
| 3644 | const extra = zir.extraData(Zir.Inst.Block, inst_data.payload_index); | |
| 3645 | const body = zir.extra[extra.end..][0..extra.data.body_len]; | |
| 3646 | const result_ref = (try sema.analyzeBodyBreak(&block_scope, @ptrCast(body))).?.operand; | |
| 3581 | const decl_bodies = decl.zirBodies(mod); | |
| 3582 | ||
| 3583 | const result_ref = (try sema.analyzeBodyBreak(&block_scope, decl_bodies.value_body)).?.operand; | |
| 3647 | 3584 | // We'll do some other bits with the Sema. Clear the type target index just |
| 3648 | 3585 | // in case they analyze any type. |
| 3649 | 3586 | sema.builtin_type_target_index = .none; |
| ... | ... | @@ -3760,13 +3697,13 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { |
| 3760 | 3697 | decl.ty = decl_tv.ty; |
| 3761 | 3698 | decl.val = Value.fromInterned((try decl_tv.val.intern(decl_tv.ty, mod))); |
| 3762 | 3699 | decl.alignment = blk: { |
| 3763 | const align_ref = decl.zirAlignRef(mod); | |
| 3764 | if (align_ref == .none) break :blk .none; | |
| 3700 | const align_body = decl_bodies.align_body orelse break :blk .none; | |
| 3701 | const align_ref = (try sema.analyzeBodyBreak(&block_scope, align_body)).?.operand; | |
| 3765 | 3702 | break :blk try sema.resolveAlign(&block_scope, align_src, align_ref); |
| 3766 | 3703 | }; |
| 3767 | 3704 | decl.@"linksection" = blk: { |
| 3768 | const linksection_ref = decl.zirLinksectionRef(mod); | |
| 3769 | if (linksection_ref == .none) break :blk .none; | |
| 3705 | const linksection_body = decl_bodies.linksection_body orelse break :blk .none; | |
| 3706 | const linksection_ref = (try sema.analyzeBodyBreak(&block_scope, linksection_body)).?.operand; | |
| 3770 | 3707 | const bytes = try sema.resolveConstString(&block_scope, section_src, linksection_ref, .{ |
| 3771 | 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 | 3723 | }; |
| 3787 | 3724 | |
| 3788 | 3725 | const target = sema.mod.getTarget(); |
| 3789 | break :blk switch (decl.zirAddrspaceRef(mod)) { | |
| 3790 | .none => switch (addrspace_ctx) { | |
| 3791 | .function => target_util.defaultAddressSpace(target, .function), | |
| 3792 | .variable => target_util.defaultAddressSpace(target, .global_mutable), | |
| 3793 | .constant => target_util.defaultAddressSpace(target, .global_constant), | |
| 3794 | else => unreachable, | |
| 3795 | }, | |
| 3796 | else => |addrspace_ref| try sema.analyzeAddressSpace(&block_scope, address_space_src, addrspace_ref, addrspace_ctx), | |
| 3726 | ||
| 3727 | const addrspace_body = decl_bodies.addrspace_body orelse break :blk switch (addrspace_ctx) { | |
| 3728 | .function => target_util.defaultAddressSpace(target, .function), | |
| 3729 | .variable => target_util.defaultAddressSpace(target, .global_mutable), | |
| 3730 | .constant => target_util.defaultAddressSpace(target, .global_constant), | |
| 3731 | else => unreachable, | |
| 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 | 3736 | decl.has_tv = true; |
| 3800 | 3737 | decl.analysis = .complete; |
| ... | ... | @@ -4133,52 +4070,32 @@ fn newEmbedFile( |
| 4133 | 4070 | } |
| 4134 | 4071 | |
| 4135 | 4072 | pub fn scanNamespace( |
| 4136 | mod: *Module, | |
| 4073 | zcu: *Zcu, | |
| 4137 | 4074 | namespace_index: Namespace.Index, |
| 4138 | extra_start: usize, | |
| 4139 | decls_len: u32, | |
| 4075 | decls: []const Zir.Inst.Index, | |
| 4140 | 4076 | parent_decl: *Decl, |
| 4141 | ) Allocator.Error!usize { | |
| 4077 | ) Allocator.Error!void { | |
| 4142 | 4078 | const tracy = trace(@src()); |
| 4143 | 4079 | defer tracy.end(); |
| 4144 | 4080 | |
| 4145 | const gpa = mod.gpa; | |
| 4146 | const namespace = mod.namespacePtr(namespace_index); | |
| 4147 | const zir = namespace.file_scope.zir; | |
| 4081 | const gpa = zcu.gpa; | |
| 4082 | const namespace = zcu.namespacePtr(namespace_index); | |
| 4148 | 4083 | |
| 4149 | try mod.comp.work_queue.ensureUnusedCapacity(decls_len); | |
| 4150 | try namespace.decls.ensureTotalCapacity(gpa, decls_len); | |
| 4084 | try zcu.comp.work_queue.ensureUnusedCapacity(decls.len); | |
| 4085 | try namespace.decls.ensureTotalCapacity(gpa, decls.len); | |
| 4151 | 4086 | |
| 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 | 4087 | var scan_decl_iter: ScanDeclIter = .{ |
| 4158 | .module = mod, | |
| 4088 | .zcu = zcu, | |
| 4159 | 4089 | .namespace_index = namespace_index, |
| 4160 | 4090 | .parent_decl = parent_decl, |
| 4161 | 4091 | }; |
| 4162 | while (decl_i < decls_len) : (decl_i += 1) { | |
| 4163 | if (decl_i % 8 == 0) { | |
| 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); | |
| 4092 | for (decls) |decl_inst| { | |
| 4093 | try scanDecl(&scan_decl_iter, decl_inst); | |
| 4176 | 4094 | } |
| 4177 | return extra_index; | |
| 4178 | 4095 | } |
| 4179 | 4096 | |
| 4180 | 4097 | const ScanDeclIter = struct { |
| 4181 | module: *Module, | |
| 4098 | zcu: *Zcu, | |
| 4182 | 4099 | namespace_index: Namespace.Index, |
| 4183 | 4100 | parent_decl: *Decl, |
| 4184 | 4101 | usingnamespace_index: usize = 0, |
| ... | ... | @@ -4186,119 +4103,112 @@ const ScanDeclIter = struct { |
| 4186 | 4103 | unnamed_test_index: usize = 0, |
| 4187 | 4104 | }; |
| 4188 | 4105 | |
| 4189 | fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Error!void { | |
| 4106 | fn scanDecl(iter: *ScanDeclIter, decl_inst: Zir.Inst.Index) Allocator.Error!void { | |
| 4190 | 4107 | const tracy = trace(@src()); |
| 4191 | 4108 | defer tracy.end(); |
| 4192 | 4109 | |
| 4193 | const mod = iter.module; | |
| 4110 | const zcu = iter.zcu; | |
| 4194 | 4111 | const namespace_index = iter.namespace_index; |
| 4195 | const namespace = mod.namespacePtr(namespace_index); | |
| 4196 | const gpa = mod.gpa; | |
| 4112 | const namespace = zcu.namespacePtr(namespace_index); | |
| 4113 | const gpa = zcu.gpa; | |
| 4197 | 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; | |
| 4199 | 4120 | |
| 4200 | // zig fmt: off | |
| 4201 | const is_pub = (flags & 0b0001) != 0; | |
| 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); | |
| 4121 | const line = iter.parent_decl.src_line + declaration.line_offset; | |
| 4122 | const decl_node = iter.parent_decl.relativeToNodeIndex(pl_node.src_node); | |
| 4214 | 4123 | |
| 4215 | 4124 | // Every Decl needs a name. |
| 4216 | var is_named_test = false; | |
| 4217 | var kind: Decl.Kind = .named; | |
| 4218 | const decl_name: InternPool.NullTerminatedString = switch (decl_name_index) { | |
| 4219 | .empty => name: { | |
| 4220 | if (export_bit) { | |
| 4221 | const i = iter.usingnamespace_index; | |
| 4222 | iter.usingnamespace_index += 1; | |
| 4223 | kind = .@"usingnamespace"; | |
| 4224 | break :name try ip.getOrPutStringFmt(gpa, "usingnamespace_{d}", .{i}); | |
| 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 | } | |
| 4125 | const decl_name: InternPool.NullTerminatedString, const kind: Decl.Kind, const is_named_test: bool = switch (declaration.name) { | |
| 4126 | .@"comptime" => info: { | |
| 4127 | const i = iter.comptime_index; | |
| 4128 | iter.comptime_index += 1; | |
| 4129 | break :info .{ | |
| 4130 | try ip.getOrPutStringFmt(gpa, "comptime_{d}", .{i}), | |
| 4131 | .@"comptime", | |
| 4132 | false, | |
| 4133 | }; | |
| 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 | 4145 | const i = iter.unnamed_test_index; |
| 4234 | 4146 | iter.unnamed_test_index += 1; |
| 4235 | kind = .@"test"; | |
| 4236 | break :name try ip.getOrPutStringFmt(gpa, "test_{d}", .{i}); | |
| 4147 | break :info .{ | |
| 4148 | try ip.getOrPutStringFmt(gpa, "test_{d}", .{i}), | |
| 4149 | .@"test", | |
| 4150 | false, | |
| 4151 | }; | |
| 4237 | 4152 | }, |
| 4238 | .decltest => name: { | |
| 4239 | is_named_test = true; | |
| 4240 | const test_name = zir.nullTerminatedString(@enumFromInt(decl_doccomment_index)); | |
| 4241 | kind = .@"test"; | |
| 4242 | break :name try ip.getOrPutStringFmt(gpa, "decltest.{s}", .{test_name}); | |
| 4153 | .decltest => info: { | |
| 4154 | assert(declaration.flags.has_doc_comment); | |
| 4155 | const name = zir.nullTerminatedString(@enumFromInt(zir.extra[extra.end])); | |
| 4156 | break :info .{ | |
| 4157 | try ip.getOrPutStringFmt(gpa, "decltest.{s}", .{name}), | |
| 4158 | .@"test", | |
| 4159 | true, | |
| 4160 | }; | |
| 4243 | 4161 | }, |
| 4244 | _ => name: { | |
| 4245 | const raw_name = zir.nullTerminatedString(decl_name_index); | |
| 4246 | if (raw_name.len == 0) { | |
| 4247 | is_named_test = true; | |
| 4248 | const test_name = zir.nullTerminatedString(@enumFromInt(@intFromEnum(decl_name_index) + 1)); | |
| 4249 | kind = .@"test"; | |
| 4250 | break :name try ip.getOrPutStringFmt(gpa, "test.{s}", .{test_name}); | |
| 4251 | } else { | |
| 4252 | break :name try ip.getOrPutString(gpa, raw_name); | |
| 4253 | } | |
| 4162 | _ => if (declaration.name.isNamedTest(zir)) .{ | |
| 4163 | try ip.getOrPutStringFmt(gpa, "test.{s}", .{zir.nullTerminatedString(declaration.name.toString(zir).?)}), | |
| 4164 | .@"test", | |
| 4165 | true, | |
| 4166 | } else .{ | |
| 4167 | try ip.getOrPutString(gpa, zir.nullTerminatedString(declaration.name.toString(zir).?)), | |
| 4168 | .named, | |
| 4169 | false, | |
| 4254 | 4170 | }, |
| 4255 | 4171 | }; |
| 4256 | 4172 | |
| 4257 | const is_exported = export_bit and decl_name_index != .empty; | |
| 4258 | 4173 | if (kind == .@"usingnamespace") try namespace.usingnamespace_set.ensureUnusedCapacity(gpa, 1); |
| 4259 | 4174 | |
| 4260 | 4175 | // We create a Decl for it regardless of analysis status. |
| 4261 | 4176 | const gop = try namespace.decls.getOrPutContextAdapted( |
| 4262 | 4177 | gpa, |
| 4263 | 4178 | decl_name, |
| 4264 | DeclAdapter{ .mod = mod }, | |
| 4265 | Namespace.DeclContext{ .module = mod }, | |
| 4179 | DeclAdapter{ .mod = zcu }, | |
| 4180 | Namespace.DeclContext{ .module = zcu }, | |
| 4266 | 4181 | ); |
| 4267 | const comp = mod.comp; | |
| 4182 | const comp = zcu.comp; | |
| 4268 | 4183 | if (!gop.found_existing) { |
| 4269 | const new_decl_index = try mod.allocateNewDecl(namespace_index, decl_node, iter.parent_decl.src_scope); | |
| 4270 | const new_decl = mod.declPtr(new_decl_index); | |
| 4184 | const new_decl_index = try zcu.allocateNewDecl(namespace_index, decl_node, iter.parent_decl.src_scope); | |
| 4185 | const new_decl = zcu.declPtr(new_decl_index); | |
| 4271 | 4186 | new_decl.kind = kind; |
| 4272 | 4187 | new_decl.name = decl_name; |
| 4273 | 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 | 4191 | new_decl.src_line = line; |
| 4277 | 4192 | gop.key_ptr.* = new_decl_index; |
| 4278 | 4193 | // Exported decls, comptime decls, usingnamespace decls, and |
| 4279 | 4194 | // test decls if in test mode, get analyzed. |
| 4280 | 4195 | const decl_mod = namespace.file_scope.mod; |
| 4281 | const want_analysis = is_exported or switch (decl_name_index) { | |
| 4282 | .empty => true, // comptime or usingnamespace decl | |
| 4283 | .unnamed_test_decl => blk: { | |
| 4284 | // test decl with no name. Skip the part where we check against | |
| 4285 | // the test name filter. | |
| 4286 | if (!comp.config.is_test) break :blk false; | |
| 4287 | if (decl_mod != mod.main_mod) break :blk false; | |
| 4288 | try mod.test_functions.put(gpa, new_decl_index, {}); | |
| 4289 | break :blk true; | |
| 4290 | }, | |
| 4291 | else => blk: { | |
| 4292 | if (!is_named_test) break :blk false; | |
| 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; | |
| 4196 | const want_analysis = declaration.flags.is_export or switch (kind) { | |
| 4197 | .anon => unreachable, | |
| 4198 | .@"comptime", .@"usingnamespace" => true, | |
| 4199 | .named => false, | |
| 4200 | .@"test" => a: { | |
| 4201 | if (!comp.config.is_test) break :a false; | |
| 4202 | if (decl_mod != zcu.main_mod) break :a false; | |
| 4203 | if (is_named_test) { | |
| 4204 | if (comp.test_filter) |test_filter| { | |
| 4205 | if (mem.indexOf(u8, ip.stringToSlice(decl_name), test_filter) == null) { | |
| 4206 | break :a false; | |
| 4207 | } | |
| 4298 | 4208 | } |
| 4299 | 4209 | } |
| 4300 | try mod.test_functions.put(gpa, new_decl_index, {}); | |
| 4301 | break :blk true; | |
| 4210 | try zcu.test_functions.put(gpa, new_decl_index, {}); | |
| 4211 | break :a true; | |
| 4302 | 4212 | }, |
| 4303 | 4213 | }; |
| 4304 | 4214 | if (want_analysis) { |
| ... | ... | @@ -4307,46 +4217,42 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err |
| 4307 | 4217 | }); |
| 4308 | 4218 | comp.work_queue.writeItemAssumeCapacity(.{ .analyze_decl = new_decl_index }); |
| 4309 | 4219 | } |
| 4310 | new_decl.is_pub = is_pub; | |
| 4311 | new_decl.is_exported = is_exported; | |
| 4312 | new_decl.has_align = has_align; | |
| 4313 | new_decl.has_linksection_or_addrspace = has_linksection_or_addrspace; | |
| 4314 | new_decl.zir_decl_index = @enumFromInt(decl_sub_index); | |
| 4220 | new_decl.is_pub = declaration.flags.is_pub; | |
| 4221 | new_decl.is_exported = declaration.flags.is_export; | |
| 4222 | new_decl.zir_decl_index = decl_inst.toOptional(); | |
| 4315 | 4223 | new_decl.alive = true; // This Decl corresponds to an AST node and therefore always alive. |
| 4316 | 4224 | return; |
| 4317 | 4225 | } |
| 4318 | 4226 | const decl_index = gop.key_ptr.*; |
| 4319 | const decl = mod.declPtr(decl_index); | |
| 4227 | const decl = zcu.declPtr(decl_index); | |
| 4320 | 4228 | if (kind == .@"test") { |
| 4321 | 4229 | const src_loc = SrcLoc{ |
| 4322 | .file_scope = decl.getFileScope(mod), | |
| 4230 | .file_scope = decl.getFileScope(zcu), | |
| 4323 | 4231 | .parent_decl_node = decl.src_node, |
| 4324 | 4232 | .lazy = .{ .token_offset = 1 }, |
| 4325 | 4233 | }; |
| 4326 | 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 | 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 | 4239 | const other_src_loc = SrcLoc{ |
| 4332 | 4240 | .file_scope = namespace.file_scope, |
| 4333 | 4241 | .parent_decl_node = decl_node, |
| 4334 | 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 | 4246 | // Update the AST node of the decl; even if its contents are unchanged, it may |
| 4339 | 4247 | // have been re-ordered. |
| 4340 | 4248 | decl.src_node = decl_node; |
| 4341 | 4249 | decl.src_line = line; |
| 4342 | 4250 | |
| 4343 | decl.is_pub = is_pub; | |
| 4344 | decl.is_exported = is_exported; | |
| 4251 | decl.is_pub = declaration.flags.is_pub; | |
| 4252 | decl.is_exported = declaration.flags.is_export; | |
| 4345 | 4253 | decl.kind = kind; |
| 4346 | decl.has_align = has_align; | |
| 4347 | decl.has_linksection_or_addrspace = has_linksection_or_addrspace; | |
| 4348 | decl.zir_decl_index = @enumFromInt(decl_sub_index); | |
| 4349 | if (decl.getOwnedFunction(mod) != null) { | |
| 4254 | decl.zir_decl_index = decl_inst.toOptional(); | |
| 4255 | if (decl.getOwnedFunction(zcu) != null) { | |
| 4350 | 4256 | // TODO Look into detecting when this would be unnecessary by storing enough state |
| 4351 | 4257 | // in `Decl` to notice that the line number did not change. |
| 4352 | 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 | 4420 | }; |
| 4515 | 4421 | defer inner_block.instructions.deinit(gpa); |
| 4516 | 4422 | |
| 4517 | const fn_info = sema.code.getFnInfo(func.zirBodyInst(ip).*); | |
| 4423 | const fn_info = sema.code.getFnInfo(func.zirBodyInst(ip).resolve(ip)); | |
| 4518 | 4424 | |
| 4519 | 4425 | // Here we are performing "runtime semantic analysis" for a function body, which means |
| 4520 | 4426 | // we must map the parameter ZIR instructions to `arg` AIR instructions. |
| ... | ... | @@ -4730,8 +4636,6 @@ pub fn allocateNewDecl( |
| 4730 | 4636 | .generation = 0, |
| 4731 | 4637 | .is_pub = false, |
| 4732 | 4638 | .is_exported = false, |
| 4733 | .has_linksection_or_addrspace = false, | |
| 4734 | .has_align = false, | |
| 4735 | 4639 | .alive = false, |
| 4736 | 4640 | .kind = .anon, |
| 4737 | 4641 | }); |
| ... | ... | @@ -6169,7 +6073,7 @@ pub fn getParamName(mod: *Module, func_index: InternPool.Index, index: u32) [:0] |
| 6169 | 6073 | const tags = file.zir.instructions.items(.tag); |
| 6170 | 6074 | const data = file.zir.instructions.items(.data); |
| 6171 | 6075 | |
| 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 | 6077 | const param = param_body[index]; |
| 6174 | 6078 | |
| 6175 | 6079 | return switch (tags[@intFromEnum(param)]) { |
src/Sema.zig+41-29| ... | ... | @@ -1224,6 +1224,10 @@ fn analyzeBodyInner( |
| 1224 | 1224 | .trap => break sema.zirTrap(block, inst), |
| 1225 | 1225 | // zig fmt: on |
| 1226 | 1226 | |
| 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 | 1231 | .extended => ext: { |
| 1228 | 1232 | const extended = datas[@intFromEnum(inst)].extended; |
| 1229 | 1233 | break :ext switch (extended.opcode) { |
| ... | ... | @@ -2704,11 +2708,12 @@ pub fn getStructType( |
| 2704 | 2708 | sema: *Sema, |
| 2705 | 2709 | decl: InternPool.DeclIndex, |
| 2706 | 2710 | namespace: InternPool.NamespaceIndex, |
| 2707 | zir_index: Zir.Inst.Index, | |
| 2711 | tracked_inst: InternPool.TrackedInst.Index, | |
| 2708 | 2712 | ) !InternPool.Index { |
| 2709 | 2713 | const mod = sema.mod; |
| 2710 | 2714 | const gpa = sema.gpa; |
| 2711 | 2715 | const ip = &mod.intern_pool; |
| 2716 | const zir_index = tracked_inst.resolve(ip); | |
| 2712 | 2717 | const extended = sema.code.instructions.items(.data)[@intFromEnum(zir_index)].extended; |
| 2713 | 2718 | assert(extended.opcode == .struct_decl); |
| 2714 | 2719 | const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small); |
| ... | ... | @@ -2736,12 +2741,14 @@ pub fn getStructType( |
| 2736 | 2741 | } |
| 2737 | 2742 | } |
| 2738 | 2743 | |
| 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; | |
| 2740 | 2747 | |
| 2741 | 2748 | const ty = try ip.getStructType(gpa, .{ |
| 2742 | 2749 | .decl = decl, |
| 2743 | 2750 | .namespace = namespace.toOptional(), |
| 2744 | .zir_index = zir_index, | |
| 2751 | .zir_index = tracked_inst, | |
| 2745 | 2752 | .layout = small.layout, |
| 2746 | 2753 | .known_non_opv = small.known_non_opv, |
| 2747 | 2754 | .is_tuple = small.is_tuple, |
| ... | ... | @@ -2791,7 +2798,8 @@ fn zirStructDecl( |
| 2791 | 2798 | errdefer mod.destroyNamespace(new_namespace_index); |
| 2792 | 2799 | |
| 2793 | 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 | 2803 | if (sema.builtin_type_target_index != .none) { |
| 2796 | 2804 | ip.resolveBuiltinType(sema.builtin_type_target_index, ty); |
| 2797 | 2805 | break :ty sema.builtin_type_target_index; |
| ... | ... | @@ -2850,7 +2858,7 @@ fn createAnonymousDeclTypeNamed( |
| 2850 | 2858 | return new_decl_index; |
| 2851 | 2859 | }, |
| 2852 | 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 | 2862 | const zir_tags = sema.code.instructions.items(.tag); |
| 2855 | 2863 | |
| 2856 | 2864 | var buf = std.ArrayList(u8).init(gpa); |
| ... | ... | @@ -2973,7 +2981,9 @@ fn zirEnumDecl( |
| 2973 | 2981 | const new_namespace = mod.namespacePtr(new_namespace_index); |
| 2974 | 2982 | errdefer if (!done) mod.destroyNamespace(new_namespace_index); |
| 2975 | 2983 | |
| 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; | |
| 2977 | 2987 | |
| 2978 | 2988 | const body = sema.code.bodySlice(extra_index, body_len); |
| 2979 | 2989 | extra_index += body.len; |
| ... | ... | @@ -3244,7 +3254,7 @@ fn zirUnionDecl( |
| 3244 | 3254 | }, |
| 3245 | 3255 | .decl = new_decl_index, |
| 3246 | 3256 | .namespace = new_namespace_index, |
| 3247 | .zir_index = inst, | |
| 3257 | .zir_index = try mod.intern_pool.trackZir(gpa, block.getFileScope(mod), inst), | |
| 3248 | 3258 | .fields_len = fields_len, |
| 3249 | 3259 | .enum_tag_ty = .none, |
| 3250 | 3260 | .field_types = &.{}, |
| ... | ... | @@ -3263,7 +3273,8 @@ fn zirUnionDecl( |
| 3263 | 3273 | new_decl.val = Value.fromInterned(union_ty); |
| 3264 | 3274 | new_namespace.ty = Type.fromInterned(union_ty); |
| 3265 | 3275 | |
| 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); | |
| 3267 | 3278 | |
| 3268 | 3279 | const decl_val = sema.analyzeDeclVal(block, src, new_decl_index); |
| 3269 | 3280 | try mod.finalizeAnonDecl(new_decl_index); |
| ... | ... | @@ -3326,7 +3337,8 @@ fn zirOpaqueDecl( |
| 3326 | 3337 | new_decl.val = Value.fromInterned(opaque_ty); |
| 3327 | 3338 | new_namespace.ty = Type.fromInterned(opaque_ty); |
| 3328 | 3339 | |
| 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); | |
| 3330 | 3342 | |
| 3331 | 3343 | const decl_val = sema.analyzeDeclVal(block, src, new_decl_index); |
| 3332 | 3344 | try mod.finalizeAnonDecl(new_decl_index); |
| ... | ... | @@ -7436,7 +7448,7 @@ fn analyzeCall( |
| 7436 | 7448 | // the AIR instructions of the callsite. The callee could be a generic function |
| 7437 | 7449 | // which means its parameter type expressions must be resolved in order and used |
| 7438 | 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 | 7452 | try ics.callee().inst_map.ensureSpaceForInstructions(gpa, fn_info.param_body); |
| 7441 | 7453 | |
| 7442 | 7454 | var arg_i: u32 = 0; |
| ... | ... | @@ -7484,7 +7496,7 @@ fn analyzeCall( |
| 7484 | 7496 | // each of the parameters, resolving the return type and providing it to the child |
| 7485 | 7497 | // `Sema` so that it can be used for the `ret_ptr` instruction. |
| 7486 | 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 | 7500 | else |
| 7489 | 7501 | try sema.resolveInst(fn_info.ret_ty_ref); |
| 7490 | 7502 | const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = 0 }; |
| ... | ... | @@ -7875,7 +7887,7 @@ fn instantiateGenericCall( |
| 7875 | 7887 | const namespace_index = fn_owner_decl.src_namespace; |
| 7876 | 7888 | const namespace = mod.namespacePtr(namespace_index); |
| 7877 | 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)); | |
| 7879 | 7891 | |
| 7880 | 7892 | const comptime_args = try sema.arena.alloc(InternPool.Index, args_info.count()); |
| 7881 | 7893 | @memset(comptime_args, .none); |
| ... | ... | @@ -9457,7 +9469,7 @@ fn funcCommon( |
| 9457 | 9469 | .is_generic = final_is_generic, |
| 9458 | 9470 | .is_noinline = is_noinline, |
| 9459 | 9471 | |
| 9460 | .zir_body_inst = func_inst, | |
| 9472 | .zir_body_inst = try ip.trackZir(gpa, block.getFileScope(mod), func_inst), | |
| 9461 | 9473 | .lbrace_line = src_locs.lbrace_line, |
| 9462 | 9474 | .rbrace_line = src_locs.rbrace_line, |
| 9463 | 9475 | .lbrace_column = @as(u16, @truncate(src_locs.columns)), |
| ... | ... | @@ -9535,7 +9547,7 @@ fn funcCommon( |
| 9535 | 9547 | .ty = func_ty, |
| 9536 | 9548 | .cc = cc, |
| 9537 | 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 | 9551 | .lbrace_line = src_locs.lbrace_line, |
| 9540 | 9552 | .rbrace_line = src_locs.rbrace_line, |
| 9541 | 9553 | .lbrace_column = @as(u16, @truncate(src_locs.columns)), |
| ... | ... | @@ -21552,7 +21564,7 @@ fn zirReify( |
| 21552 | 21564 | .namespace = new_namespace_index, |
| 21553 | 21565 | .enum_tag_ty = enum_tag_ty, |
| 21554 | 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 | 21568 | .flags = .{ |
| 21557 | 21569 | .layout = layout, |
| 21558 | 21570 | .status = .have_field_types, |
| ... | ... | @@ -21720,7 +21732,7 @@ fn reifyStruct( |
| 21720 | 21732 | const ty = try ip.getStructType(gpa, .{ |
| 21721 | 21733 | .decl = new_decl_index, |
| 21722 | 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 | 21736 | .layout = layout, |
| 21725 | 21737 | .known_non_opv = false, |
| 21726 | 21738 | .fields_len = fields_len, |
| ... | ... | @@ -35592,7 +35604,8 @@ fn semaBackingIntType(mod: *Module, struct_type: InternPool.Key.StructType) Comp |
| 35592 | 35604 | break :blk accumulator; |
| 35593 | 35605 | }; |
| 35594 | 35606 | |
| 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 | 35609 | assert(extended.opcode == .struct_decl); |
| 35597 | 35610 | const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small); |
| 35598 | 35611 | |
| ... | ... | @@ -35612,7 +35625,7 @@ fn semaBackingIntType(mod: *Module, struct_type: InternPool.Key.StructType) Comp |
| 35612 | 35625 | break :blk try sema.resolveType(&block, backing_int_src, backing_int_ref); |
| 35613 | 35626 | } else { |
| 35614 | 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 | 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 | 36353 | } |
| 36341 | 36354 | |
| 36342 | 36355 | // Skip over decls. |
| 36343 | var decls_it = zir.declIteratorInner(extra_index, decls_len); | |
| 36344 | while (decls_it.next()) |_| {} | |
| 36345 | extra_index = decls_it.extra_index; | |
| 36356 | extra_index += decls_len; | |
| 36346 | 36357 | |
| 36347 | 36358 | return .{ fields_len, small, extra_index }; |
| 36348 | 36359 | } |
| ... | ... | @@ -36358,7 +36369,7 @@ fn semaStructFields( |
| 36358 | 36369 | const decl = mod.declPtr(decl_index); |
| 36359 | 36370 | const namespace_index = struct_type.namespace.unwrap() orelse decl.src_namespace; |
| 36360 | 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); | |
| 36362 | 36373 | |
| 36363 | 36374 | const fields_len, const small, var extra_index = structZirInfo(zir, zir_index); |
| 36364 | 36375 | |
| ... | ... | @@ -36629,7 +36640,7 @@ fn semaStructFieldInits( |
| 36629 | 36640 | const decl = mod.declPtr(decl_index); |
| 36630 | 36641 | const namespace_index = struct_type.namespace.unwrap() orelse decl.src_namespace; |
| 36631 | 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 | 36644 | const fields_len, const small, var extra_index = structZirInfo(zir, zir_index); |
| 36634 | 36645 | |
| 36635 | 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 | 36789 | const ip = &mod.intern_pool; |
| 36779 | 36790 | const decl_index = union_type.decl; |
| 36780 | 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 | 36794 | assert(extended.opcode == .union_decl); |
| 36783 | 36795 | const small: Zir.Inst.UnionDecl.Small = @bitCast(extended.small); |
| 36784 | 36796 | var extra_index: usize = extended.operand; |
| ... | ... | @@ -36811,9 +36823,7 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Key.Un |
| 36811 | 36823 | } else 0; |
| 36812 | 36824 | |
| 36813 | 36825 | // Skip over decls. |
| 36814 | var decls_it = zir.declIteratorInner(extra_index, decls_len); | |
| 36815 | while (decls_it.next()) |_| {} | |
| 36816 | extra_index = decls_it.extra_index; | |
| 36826 | extra_index += decls_len; | |
| 36817 | 36827 | |
| 36818 | 36828 | const body = zir.bodySlice(extra_index, body_len); |
| 36819 | 36829 | extra_index += body.len; |
| ... | ... | @@ -37810,10 +37820,12 @@ pub fn analyzeAddressSpace( |
| 37810 | 37820 | ctx: AddressSpaceContext, |
| 37811 | 37821 | ) !std.builtin.AddressSpace { |
| 37812 | 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 | 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 | 37829 | const target = sema.mod.getTarget(); |
| 37818 | 37830 | const arch = target.cpu.arch; |
| 37819 | 37831 |
src/Zir.zig+213-187| ... | ... | @@ -30,7 +30,7 @@ instructions: std.MultiArrayList(Inst).Slice, |
| 30 | 30 | /// is referencing the data here whether they want to store both index and length, |
| 31 | 31 | /// thus allowing null bytes, or store only index, and use null-termination. The |
| 32 | 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. | |
| 34 | 34 | string_bytes: []u8, |
| 35 | 35 | /// The meaning of this data is determined by `Inst.Tag` value. |
| 36 | 36 | /// The first few indexes are reserved. See `ExtraIndex` for the values. |
| ... | ... | @@ -60,21 +60,6 @@ pub const ExtraIndex = enum(u32) { |
| 60 | 60 | imports, |
| 61 | 61 | |
| 62 | 62 | _, |
| 63 | ||
| 64 | pub fn toOptional(i: ExtraIndex) OptionalExtraIndex { | |
| 65 | return @enumFromInt(@intFromEnum(i)); | |
| 66 | } | |
| 67 | }; | |
| 68 | ||
| 69 | pub 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 | }; |
| 79 | 64 | |
| 80 | 65 | fn ExtraData(comptime T: type) type { |
| ... | ... | @@ -93,6 +78,7 @@ pub fn extraData(code: Zir, comptime T: type, index: usize) ExtraData(T) { |
| 93 | 78 | |
| 94 | 79 | Inst.Ref, |
| 95 | 80 | Inst.Index, |
| 81 | Inst.Declaration.Name, | |
| 96 | 82 | NullTerminatedString, |
| 97 | 83 | => @enumFromInt(code.extra[i]), |
| 98 | 84 | |
| ... | ... | @@ -102,6 +88,7 @@ pub fn extraData(code: Zir, comptime T: type, index: usize) ExtraData(T) { |
| 102 | 88 | Inst.SwitchBlock.Bits, |
| 103 | 89 | Inst.SwitchBlockErrUnion.Bits, |
| 104 | 90 | Inst.FuncFancy.Bits, |
| 91 | Inst.Declaration.Flags, | |
| 105 | 92 | => @bitCast(code.extra[i]), |
| 106 | 93 | |
| 107 | 94 | else => @compileError("bad field type"), |
| ... | ... | @@ -116,8 +103,6 @@ pub fn extraData(code: Zir, comptime T: type, index: usize) ExtraData(T) { |
| 116 | 103 | |
| 117 | 104 | pub const NullTerminatedString = enum(u32) { |
| 118 | 105 | empty = 0, |
| 119 | unnamed_test_decl = 1, | |
| 120 | decltest = 2, | |
| 121 | 106 | _, |
| 122 | 107 | }; |
| 123 | 108 | |
| ... | ... | @@ -304,6 +289,12 @@ pub const Inst = struct { |
| 304 | 289 | /// a noreturn instruction. |
| 305 | 290 | /// Uses the `pl_node` union field. Payload is `Block`. |
| 306 | 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 | 298 | /// Implements `suspend {...}`. |
| 308 | 299 | /// Uses the `pl_node` union field. Payload is `Block`. |
| 309 | 300 | suspend_block, |
| ... | ... | @@ -1092,6 +1083,7 @@ pub const Inst = struct { |
| 1092 | 1083 | .block, |
| 1093 | 1084 | .block_comptime, |
| 1094 | 1085 | .block_inline, |
| 1086 | .declaration, | |
| 1095 | 1087 | .suspend_block, |
| 1096 | 1088 | .loop, |
| 1097 | 1089 | .bool_br_and, |
| ... | ... | @@ -1405,6 +1397,7 @@ pub const Inst = struct { |
| 1405 | 1397 | .block, |
| 1406 | 1398 | .block_comptime, |
| 1407 | 1399 | .block_inline, |
| 1400 | .declaration, | |
| 1408 | 1401 | .suspend_block, |
| 1409 | 1402 | .loop, |
| 1410 | 1403 | .bool_br_and, |
| ... | ... | @@ -1639,6 +1632,7 @@ pub const Inst = struct { |
| 1639 | 1632 | .block = .pl_node, |
| 1640 | 1633 | .block_comptime = .pl_node, |
| 1641 | 1634 | .block_inline = .pl_node, |
| 1635 | .declaration = .pl_node, | |
| 1642 | 1636 | .suspend_block = .pl_node, |
| 1643 | 1637 | .bool_not = .un_node, |
| 1644 | 1638 | .bool_br_and = .bool_br, |
| ... | ... | @@ -2508,6 +2502,7 @@ pub const Inst = struct { |
| 2508 | 2502 | /// If this is 1 it means return_type is a simple Ref |
| 2509 | 2503 | ret_body_len: u32, |
| 2510 | 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 | 2506 | param_block: Index, |
| 2512 | 2507 | body_len: u32, |
| 2513 | 2508 | |
| ... | ... | @@ -2565,6 +2560,7 @@ pub const Inst = struct { |
| 2565 | 2560 | /// 18. src_locs: Func.SrcLocs // if body_len != 0 |
| 2566 | 2561 | pub const FuncFancy = struct { |
| 2567 | 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 | 2564 | param_block: Index, |
| 2569 | 2565 | body_len: u32, |
| 2570 | 2566 | bits: Bits, |
| ... | ... | @@ -2632,6 +2628,116 @@ pub const Inst = struct { |
| 2632 | 2628 | body_len: u32, |
| 2633 | 2629 | }; |
| 2634 | 2630 | |
| 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 | 2741 | /// Stored inside extra, with trailing arguments according to `args_len`. |
| 2636 | 2742 | /// Implicit 0. arg_0_start: u32, // always same as `args_len` |
| 2637 | 2743 | /// 1. arg_end: u32, // for each `args_len` |
| ... | ... | @@ -2913,37 +3019,14 @@ pub const Inst = struct { |
| 2913 | 3019 | /// 3. backing_int_body_len: u32, // if has_backing_int |
| 2914 | 3020 | /// 4. backing_int_ref: Ref, // if has_backing_int and backing_int_body_len is 0 |
| 2915 | 3021 | /// 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 decls | |
| 2917 | /// - sets of 4 bits: | |
| 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 | |
| 3022 | /// 6. decl: Index, // for every decls_len; points to a `declaration` instruction | |
| 3023 | /// 7. flags: u32 // for every 8 fields | |
| 2941 | 3024 | /// - sets of 4 bits: |
| 2942 | 3025 | /// 0b000X: whether corresponding field has an align expression |
| 2943 | 3026 | /// 0b00X0: whether corresponding field has a default expression |
| 2944 | 3027 | /// 0b0X00: whether corresponding field is comptime |
| 2945 | 3028 | /// 0bX000: whether corresponding field has a type expression |
| 2946 | /// 9. fields: { // for every fields_len | |
| 3029 | /// 8. fields: { // for every fields_len | |
| 2947 | 3030 | /// field_name: u32, // if !is_tuple |
| 2948 | 3031 | /// doc_comment: NullTerminatedString, // .empty if no doc comment |
| 2949 | 3032 | /// field_type: Ref, // if corresponding bit is not set. none means anytype. |
| ... | ... | @@ -3009,33 +3092,11 @@ pub const Inst = struct { |
| 3009 | 3092 | /// 2. body_len: u32, // if has_body_len |
| 3010 | 3093 | /// 3. fields_len: u32, // if has_fields_len |
| 3011 | 3094 | /// 4. decls_len: u32, // if has_decls_len |
| 3012 | /// 5. decl_bits: u32 // for every 8 decls | |
| 3013 | /// - sets of 4 bits: | |
| 3014 | /// 0b000X: whether corresponding decl is pub | |
| 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 | |
| 3095 | /// 5. decl: Index, // for every decls_len; points to a `declaration` instruction | |
| 3096 | /// 6. inst: Index // for every body_len | |
| 3097 | /// 7. has_bits: u32 // for every 32 fields | |
| 3037 | 3098 | /// - the bit is whether corresponding field has an value expression |
| 3038 | /// 9. fields: { // for every fields_len | |
| 3099 | /// 8. fields: { // for every fields_len | |
| 3039 | 3100 | /// field_name: u32, |
| 3040 | 3101 | /// doc_comment: u32, // .empty if no doc_comment |
| 3041 | 3102 | /// value: Ref, // if corresponding bit is set |
| ... | ... | @@ -3059,37 +3120,15 @@ pub const Inst = struct { |
| 3059 | 3120 | /// 2. body_len: u32, // if has_body_len |
| 3060 | 3121 | /// 3. fields_len: u32, // if has_fields_len |
| 3061 | 3122 | /// 4. decls_len: u32, // if has_decls_len |
| 3062 | /// 5. decl_bits: u32 // for every 8 decls | |
| 3063 | /// - sets of 4 bits: | |
| 3064 | /// 0b000X: whether corresponding decl is pub | |
| 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 | |
| 3123 | /// 5. decl: Index, // for every decls_len; points to a `declaration` instruction | |
| 3124 | /// 6. inst: Index // for every body_len | |
| 3125 | /// 7. has_bits: u32 // for every 8 fields | |
| 3087 | 3126 | /// - sets of 4 bits: |
| 3088 | 3127 | /// 0b000X: whether corresponding field has a type expression |
| 3089 | 3128 | /// 0b00X0: whether corresponding field has a align expression |
| 3090 | 3129 | /// 0b0X00: whether corresponding field has a tag value expression |
| 3091 | 3130 | /// 0bX000: unused |
| 3092 | /// 9. fields: { // for every fields_len | |
| 3131 | /// 8. fields: { // for every fields_len | |
| 3093 | 3132 | /// field_name: NullTerminatedString, // null terminated string index |
| 3094 | 3133 | /// doc_comment: NullTerminatedString, // .empty if no doc comment |
| 3095 | 3134 | /// field_type: Ref, // if corresponding bit is set |
| ... | ... | @@ -3121,29 +3160,7 @@ pub const Inst = struct { |
| 3121 | 3160 | /// Trailing: |
| 3122 | 3161 | /// 0. src_node: i32, // if has_src_node |
| 3123 | 3162 | /// 1. decls_len: u32, // if has_decls_len |
| 3124 | /// 2. decl_bits: u32 // for every 8 decls | |
| 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 | /// } | |
| 3163 | /// 2. decl: Index, // for every decls_len; points to a `declaration` instruction | |
| 3147 | 3164 | pub const OpaqueDecl = struct { |
| 3148 | 3165 | pub const Small = packed struct { |
| 3149 | 3166 | has_src_node: bool, |
| ... | ... | @@ -3407,44 +3424,17 @@ pub const Inst = struct { |
| 3407 | 3424 | pub const SpecialProng = enum { none, @"else", under }; |
| 3408 | 3425 | |
| 3409 | 3426 | pub const DeclIterator = struct { |
| 3410 | extra_index: usize, | |
| 3411 | bit_bag_index: usize, | |
| 3412 | cur_bit_bag: u32, | |
| 3413 | decl_i: u32, | |
| 3414 | decls_len: u32, | |
| 3427 | extra_index: u32, | |
| 3428 | decls_remaining: u32, | |
| 3415 | 3429 | zir: Zir, |
| 3416 | 3430 | |
| 3417 | pub const Item = struct { | |
| 3418 | name: [:0]const u8, | |
| 3419 | sub_index: ExtraIndex, | |
| 3420 | flags: u4, | |
| 3421 | }; | |
| 3422 | ||
| 3423 | pub fn next(it: *DeclIterator) ?Item { | |
| 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 | }; | |
| 3431 | pub fn next(it: *DeclIterator) ?Inst.Index { | |
| 3432 | if (it.decls_remaining == 0) return null; | |
| 3433 | const decl_inst: Zir.Inst.Index = @enumFromInt(it.zir.extra[it.extra_index]); | |
| 3434 | it.extra_index += 1; | |
| 3435 | it.decls_remaining -= 1; | |
| 3436 | assert(it.zir.instructions.items(.tag)[@intFromEnum(decl_inst)] == .declaration); | |
| 3437 | return decl_inst; | |
| 3448 | 3438 | } |
| 3449 | 3439 | }; |
| 3450 | 3440 | |
| ... | ... | @@ -3454,14 +3444,18 @@ pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator { |
| 3454 | 3444 | switch (tags[@intFromEnum(decl_inst)]) { |
| 3455 | 3445 | // Functions are allowed and yield no iterations. |
| 3456 | 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 | }, | |
| 3458 | 3452 | |
| 3459 | 3453 | .extended => { |
| 3460 | 3454 | const extended = datas[@intFromEnum(decl_inst)].extended; |
| 3461 | 3455 | switch (extended.opcode) { |
| 3462 | 3456 | .struct_decl => { |
| 3463 | 3457 | const small: Inst.StructDecl.Small = @bitCast(extended.small); |
| 3464 | var extra_index: usize = extended.operand; | |
| 3458 | var extra_index: u32 = extended.operand; | |
| 3465 | 3459 | extra_index += @intFromBool(small.has_src_node); |
| 3466 | 3460 | extra_index += @intFromBool(small.has_fields_len); |
| 3467 | 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 | 3474 | } |
| 3481 | 3475 | } |
| 3482 | 3476 | |
| 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 | 3483 | .enum_decl => { |
| 3486 | 3484 | const small: Inst.EnumDecl.Small = @bitCast(extended.small); |
| 3487 | var extra_index: usize = extended.operand; | |
| 3485 | var extra_index: u32 = extended.operand; | |
| 3488 | 3486 | extra_index += @intFromBool(small.has_src_node); |
| 3489 | 3487 | extra_index += @intFromBool(small.has_tag_type); |
| 3490 | 3488 | extra_index += @intFromBool(small.has_body_len); |
| ... | ... | @@ -3495,11 +3493,15 @@ pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator { |
| 3495 | 3493 | break :decls_len decls_len; |
| 3496 | 3494 | } else 0; |
| 3497 | 3495 | |
| 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 | 3502 | .union_decl => { |
| 3501 | 3503 | const small: Inst.UnionDecl.Small = @bitCast(extended.small); |
| 3502 | var extra_index: usize = extended.operand; | |
| 3504 | var extra_index: u32 = extended.operand; | |
| 3503 | 3505 | extra_index += @intFromBool(small.has_src_node); |
| 3504 | 3506 | extra_index += @intFromBool(small.has_tag_type); |
| 3505 | 3507 | extra_index += @intFromBool(small.has_body_len); |
| ... | ... | @@ -3510,11 +3512,15 @@ pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator { |
| 3510 | 3512 | break :decls_len decls_len; |
| 3511 | 3513 | } else 0; |
| 3512 | 3514 | |
| 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 | 3521 | .opaque_decl => { |
| 3516 | 3522 | const small: Inst.OpaqueDecl.Small = @bitCast(extended.small); |
| 3517 | var extra_index: usize = extended.operand; | |
| 3523 | var extra_index: u32 = extended.operand; | |
| 3518 | 3524 | extra_index += @intFromBool(small.has_src_node); |
| 3519 | 3525 | const decls_len = if (small.has_decls_len) decls_len: { |
| 3520 | 3526 | const decls_len = zir.extra[extra_index]; |
| ... | ... | @@ -3522,7 +3528,11 @@ pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator { |
| 3522 | 3528 | break :decls_len decls_len; |
| 3523 | 3529 | } else 0; |
| 3524 | 3530 | |
| 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 | 3537 | else => unreachable, |
| 3528 | 3538 | } |
| ... | ... | @@ -3531,25 +3541,17 @@ pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator { |
| 3531 | 3541 | } |
| 3532 | 3542 | } |
| 3533 | 3543 | |
| 3534 | pub 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 | 3544 | /// The iterator would have to allocate memory anyway to iterate. So here we populate |
| 3547 | 3545 | /// an ArrayList as the result. |
| 3548 | pub fn findDecls(zir: Zir, list: *std.ArrayList(Inst.Index), decl_sub_index: ExtraIndex) !void { | |
| 3549 | const block_inst: Zir.Inst.Index = @enumFromInt(zir.extra[@intFromEnum(decl_sub_index) + 6]); | |
| 3546 | pub fn findDecls(zir: Zir, list: *std.ArrayList(Inst.Index), decl_inst: Zir.Inst.Index) !void { | |
| 3550 | 3547 | list.clearRetainingCapacity(); |
| 3548 | const declaration, const extra_end = zir.getDeclaration(decl_inst); | |
| 3549 | const bodies = declaration.getBodies(extra_end, zir); | |
| 3551 | 3550 | |
| 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 | } |
| 3554 | 3556 | |
| 3555 | 3557 | fn findDeclsInner( |
| ... | ... | @@ -3791,8 +3793,17 @@ pub fn getParamBody(zir: Zir, fn_inst: Inst.Index) []const Zir.Inst.Index { |
| 3791 | 3793 | else => unreachable, |
| 3792 | 3794 | }; |
| 3793 | 3795 | |
| 3794 | const param_block = zir.extraData(Inst.Block, datas[@intFromEnum(param_block_index)].pl_node.payload_index); | |
| 3795 | return zir.bodySlice(param_block.end, param_block.data.body_len); | |
| 3796 | switch (tags[@intFromEnum(param_block_index)]) { | |
| 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 | } |
| 3797 | 3808 | |
| 3798 | 3809 | 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 | 3900 | else => unreachable, |
| 3890 | 3901 | }; |
| 3891 | switch (tags[@intFromEnum(info.param_block)]) { | |
| 3892 | .block, .block_comptime, .block_inline => {}, // OK | |
| 3893 | else => unreachable, // assertion failure | |
| 3894 | } | |
| 3895 | const param_block = zir.extraData(Inst.Block, datas[@intFromEnum(info.param_block)].pl_node.payload_index); | |
| 3896 | const param_body = zir.bodySlice(param_block.end, param_block.data.body_len); | |
| 3902 | const param_body = switch (tags[@intFromEnum(info.param_block)]) { | |
| 3903 | .block, .block_comptime, .block_inline => param_body: { | |
| 3904 | const param_block = zir.extraData(Inst.Block, datas[@intFromEnum(info.param_block)].pl_node.payload_index); | |
| 3905 | break :param_body zir.bodySlice(param_block.end, param_block.data.body_len); | |
| 3906 | }, | |
| 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 | 3913 | var total_params_len: u32 = 0; |
| 3898 | 3914 | for (param_body) |inst| { |
| 3899 | 3915 | switch (tags[@intFromEnum(inst)]) { |
| ... | ... | @@ -3912,3 +3928,13 @@ pub fn getFnInfo(zir: Zir, fn_inst: Inst.Index) FnInfo { |
| 3912 | 3928 | .total_params_len = total_params_len, |
| 3913 | 3929 | }; |
| 3914 | 3930 | } |
| 3931 | ||
| 3932 | pub 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 | 6855 | var inst_map: std.AutoHashMapUnmanaged(Zir.Inst.Index, Zir.Inst.Index) = .{}; |
| 6856 | 6856 | defer inst_map.deinit(gpa); |
| 6857 | 6857 | |
| 6858 | var extra_map: std.AutoHashMapUnmanaged(Zir.ExtraIndex, Zir.ExtraIndex) = .{}; | |
| 6859 | defer extra_map.deinit(gpa); | |
| 6860 | ||
| 6861 | try Module.mapOldZirToNew(gpa, old_zir, file.zir, &inst_map, &extra_map); | |
| 6858 | try Module.mapOldZirToNew(gpa, old_zir, file.zir, &inst_map); | |
| 6862 | 6859 | |
| 6863 | 6860 | var bw = io.bufferedWriter(io.getStdOut().writer()); |
| 6864 | 6861 | const stdout = bw.writer(); |
| ... | ... | @@ -6867,16 +6864,8 @@ pub fn cmdChangelist( |
| 6867 | 6864 | var it = inst_map.iterator(); |
| 6868 | 6865 | while (it.next()) |entry| { |
| 6869 | 6866 | try stdout.print(" %{d} => %{d}\n", .{ |
| 6870 | entry.key_ptr.*, entry.value_ptr.*, | |
| 6871 | }); | |
| 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.*, | |
| 6867 | @intFromEnum(entry.key_ptr.*), | |
| 6868 | @intFromEnum(entry.value_ptr.*), | |
| 6880 | 6869 | }); |
| 6881 | 6870 | } |
| 6882 | 6871 | } |
src/print_zir.zig+67-122| ... | ... | @@ -521,6 +521,8 @@ const Writer = struct { |
| 521 | 521 | .@"defer" => try self.writeDefer(stream, inst), |
| 522 | 522 | .defer_err_code => try self.writeDeferErrCode(stream, inst), |
| 523 | 523 | |
| 524 | .declaration => try self.writeDeclaration(stream, inst), | |
| 525 | ||
| 524 | 526 | .extended => try self.writeExtended(stream, inst), |
| 525 | 527 | } |
| 526 | 528 | } |
| ... | ... | @@ -1454,8 +1456,9 @@ const Writer = struct { |
| 1454 | 1456 | |
| 1455 | 1457 | try stream.writeAll("{\n"); |
| 1456 | 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 | 1460 | self.indent -= 2; |
| 1461 | extra_index += decls_len; | |
| 1459 | 1462 | try stream.writeByteNTimes(' ', self.indent); |
| 1460 | 1463 | try stream.writeAll("}, "); |
| 1461 | 1464 | } |
| ... | ... | @@ -1634,8 +1637,9 @@ const Writer = struct { |
| 1634 | 1637 | |
| 1635 | 1638 | try stream.writeAll("{\n"); |
| 1636 | 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 | 1641 | self.indent -= 2; |
| 1642 | extra_index += decls_len; | |
| 1639 | 1643 | try stream.writeByteNTimes(' ', self.indent); |
| 1640 | 1644 | try stream.writeAll("}"); |
| 1641 | 1645 | } |
| ... | ... | @@ -1727,124 +1731,6 @@ const Writer = struct { |
| 1727 | 1731 | try self.writeSrcNode(stream, src_node); |
| 1728 | 1732 | } |
| 1729 | 1733 | |
| 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 | 1734 | fn writeEnumDecl(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void { |
| 1849 | 1735 | const small = @as(Zir.Inst.EnumDecl.Small, @bitCast(extended.small)); |
| 1850 | 1736 | var extra_index: usize = extended.operand; |
| ... | ... | @@ -1891,8 +1777,9 @@ const Writer = struct { |
| 1891 | 1777 | |
| 1892 | 1778 | try stream.writeAll("{\n"); |
| 1893 | 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 | 1781 | self.indent -= 2; |
| 1782 | extra_index += decls_len; | |
| 1896 | 1783 | try stream.writeByteNTimes(' ', self.indent); |
| 1897 | 1784 | try stream.writeAll("}, "); |
| 1898 | 1785 | } |
| ... | ... | @@ -1988,7 +1875,7 @@ const Writer = struct { |
| 1988 | 1875 | |
| 1989 | 1876 | try stream.writeAll("{\n"); |
| 1990 | 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 | 1879 | self.indent -= 2; |
| 1993 | 1880 | try stream.writeByteNTimes(' ', self.indent); |
| 1994 | 1881 | try stream.writeAll("})"); |
| ... | ... | @@ -2762,6 +2649,64 @@ const Writer = struct { |
| 2762 | 2649 | try stream.writeByte(')'); |
| 2763 | 2650 | } |
| 2764 | 2651 | |
| 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 | 2710 | fn writeInstRef(self: *Writer, stream: anytype, ref: Zir.Inst.Ref) !void { |
| 2766 | 2711 | if (ref == .none) { |
| 2767 | 2712 | return stream.writeAll(".none"); |