| author | |
| committer | |
| log | ae845a33c04fb287ae5a7445743c2b570e40ca1f |
| tree | 65bbaa19d241453a95f7a1561d2815106cf36844 |
| parent | 993a83081a975464d1201597cf6f4cb7f6735284 |
| signature |
This commit changes how declarations (`const`, `fn`, `usingnamespace`,
etc) are represented in ZIR. Previously, these were represented in the
container type's extra data (e.g. as trailing data on a `struct_decl`).
However, this introduced the complexity of the ZIR mapping logic having
to also correlate some ZIR extra data indices. That isn't really a
problem today, but it's tricky for the introduction of `TrackedInst` in
the commit following this one. Instead, these type declarations now
simply contain a trailing list of ZIR indices to `declaration`
instructions, which directly encode all data related to the declaration
(including containing the declaration's body). Additionally, the ZIR for
`align` etc have been split out into their own bodies. This is not
strictly necessary, but it's much simpler to understand for an
insignificant cost in bytes, and will simplify the resolution of #131
(where we may need to evaluate the pointer type, including align etc,
without immediately evaluating the value body).8 files changed, 863 insertions(+), 939 deletions(-)
src/AstGen.zig+225-159| ... | @@ -86,6 +86,7 @@ fn setExtra(astgen: *AstGen, index: usize, extra: anytype) void { | ... | @@ -86,6 +86,7 @@ fn setExtra(astgen: *AstGen, index: usize, extra: anytype) void { |
| 86 | 86 | ||
| 87 | Zir.Inst.Ref, | 87 | Zir.Inst.Ref, |
| 88 | Zir.Inst.Index, | 88 | Zir.Inst.Index, |
| 89 | Zir.Inst.Declaration.Name, | ||
| 89 | Zir.NullTerminatedString, | 90 | Zir.NullTerminatedString, |
| 90 | => @intFromEnum(@field(extra, field.name)), | 91 | => @intFromEnum(@field(extra, field.name)), |
| 91 | 92 | ||
| ... | @@ -95,6 +96,7 @@ fn setExtra(astgen: *AstGen, index: usize, extra: anytype) void { | ... | @@ -95,6 +96,7 @@ fn setExtra(astgen: *AstGen, index: usize, extra: anytype) void { |
| 95 | Zir.Inst.SwitchBlock.Bits, | 96 | Zir.Inst.SwitchBlock.Bits, |
| 96 | Zir.Inst.SwitchBlockErrUnion.Bits, | 97 | Zir.Inst.SwitchBlockErrUnion.Bits, |
| 97 | Zir.Inst.FuncFancy.Bits, | 98 | Zir.Inst.FuncFancy.Bits, |
| 99 | Zir.Inst.Declaration.Flags, | ||
| 98 | => @bitCast(@field(extra, field.name)), | 100 | => @bitCast(@field(extra, field.name)), |
| 99 | 101 | ||
| 100 | else => @compileError("bad field type"), | 102 | else => @compileError("bad field type"), |
| ... | @@ -132,8 +134,8 @@ pub fn generate(gpa: Allocator, tree: Ast) Allocator.Error!Zir { | ... | @@ -132,8 +134,8 @@ pub fn generate(gpa: Allocator, tree: Ast) Allocator.Error!Zir { |
| 132 | }; | 134 | }; |
| 133 | defer astgen.deinit(gpa); | 135 | defer astgen.deinit(gpa); |
| 134 | 136 | ||
| 135 | // String table indexes 0, 1, 2 are reserved for special meaning. | 137 | // String table index 0 is reserved for `NullTerminatedString.empty`. |
| 136 | try astgen.string_bytes.appendSlice(gpa, &[_]u8{ 0, 0, 0 }); | 138 | try astgen.string_bytes.append(gpa, 0); |
| 137 | 139 | ||
| 138 | // We expect at least as many ZIR instructions and extra data items | 140 | // We expect at least as many ZIR instructions and extra data items |
| 139 | // as AST nodes. | 141 | // as AST nodes. |
| ... | @@ -355,8 +357,13 @@ const ResultInfo = struct { | ... | @@ -355,8 +357,13 @@ const ResultInfo = struct { |
| 355 | }; | 357 | }; |
| 356 | }; | 358 | }; |
| 357 | 359 | ||
| 360 | /// TODO: modify Sema to remove in favour of `coerced_align_ri` | ||
| 358 | const align_ri: ResultInfo = .{ .rl = .{ .ty = .u29_type } }; | 361 | const align_ri: ResultInfo = .{ .rl = .{ .ty = .u29_type } }; |
| 359 | const coerced_align_ri: ResultInfo = .{ .rl = .{ .coerced_ty = .u29_type } }; | 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 | const bool_ri: ResultInfo = .{ .rl = .{ .ty = .bool_type } }; | 367 | const bool_ri: ResultInfo = .{ .rl = .{ .ty = .bool_type } }; |
| 361 | const type_ri: ResultInfo = .{ .rl = .{ .ty = .type_type } }; | 368 | const type_ri: ResultInfo = .{ .rl = .{ .ty = .type_type } }; |
| 362 | const coerced_type_ri: ResultInfo = .{ .rl = .{ .coerced_ty = .type_type } }; | 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,6 +2599,7 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As |
| 2592 | .block, | 2599 | .block, |
| 2593 | .block_comptime, | 2600 | .block_comptime, |
| 2594 | .block_inline, | 2601 | .block_inline, |
| 2602 | .declaration, | ||
| 2595 | .suspend_block, | 2603 | .suspend_block, |
| 2596 | .loop, | 2604 | .loop, |
| 2597 | .bool_br_and, | 2605 | .bool_br_and, |
| ... | @@ -3783,7 +3791,7 @@ fn ptrType( | ... | @@ -3783,7 +3791,7 @@ fn ptrType( |
| 3783 | gz.astgen.source_line = source_line; | 3791 | gz.astgen.source_line = source_line; |
| 3784 | gz.astgen.source_column = source_column; | 3792 | gz.astgen.source_column = source_column; |
| 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 | trailing_count += 1; | 3795 | trailing_count += 1; |
| 3788 | } | 3796 | } |
| 3789 | if (ptr_info.ast.align_node != 0) { | 3797 | if (ptr_info.ast.align_node != 0) { |
| ... | @@ -3899,8 +3907,6 @@ fn arrayTypeSentinel(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node. | ... | @@ -3899,8 +3907,6 @@ fn arrayTypeSentinel(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node. |
| 3899 | const WipMembers = struct { | 3907 | const WipMembers = struct { |
| 3900 | payload: *ArrayListUnmanaged(u32), | 3908 | payload: *ArrayListUnmanaged(u32), |
| 3901 | payload_top: usize, | 3909 | payload_top: usize, |
| 3902 | decls_start: u32, | ||
| 3903 | decls_end: u32, | ||
| 3904 | field_bits_start: u32, | 3910 | field_bits_start: u32, |
| 3905 | fields_start: u32, | 3911 | fields_start: u32, |
| 3906 | fields_end: u32, | 3912 | fields_end: u32, |
| ... | @@ -3908,43 +3914,27 @@ const WipMembers = struct { | ... | @@ -3908,43 +3914,27 @@ const WipMembers = struct { |
| 3908 | field_index: u32 = 0, | 3914 | field_index: u32 = 0, |
| 3909 | 3915 | ||
| 3910 | const Self = @This(); | 3916 | const Self = @This(); |
| 3911 | /// struct, union, enum, and opaque decls all use same 4 bits per decl | ||
| 3912 | const bits_per_decl = 4; | ||
| 3913 | const decls_per_u32 = 32 / bits_per_decl; | ||
| 3914 | /// struct, union, enum, and opaque decls all have maximum size of 11 u32 slots | ||
| 3915 | /// (4 for src_hash + line + name + value + doc_comment + align + link_section + address_space ) | ||
| 3916 | const max_decl_size = 11; | ||
| 3917 | 3917 | ||
| 3918 | fn init(gpa: Allocator, payload: *ArrayListUnmanaged(u32), decl_count: u32, field_count: u32, comptime bits_per_field: u32, comptime max_field_size: u32) Allocator.Error!Self { | 3918 | fn init(gpa: Allocator, payload: *ArrayListUnmanaged(u32), decl_count: u32, field_count: u32, comptime bits_per_field: u32, comptime max_field_size: u32) Allocator.Error!Self { |
| 3919 | const payload_top: u32 = @intCast(payload.items.len); | 3919 | const payload_top: u32 = @intCast(payload.items.len); |
| 3920 | const decls_start = payload_top + (decl_count + decls_per_u32 - 1) / decls_per_u32; | 3920 | const field_bits_start = payload_top + decl_count; |
| 3921 | const field_bits_start = decls_start + decl_count * max_decl_size; | ||
| 3922 | const fields_start = field_bits_start + if (bits_per_field > 0) blk: { | 3921 | const fields_start = field_bits_start + if (bits_per_field > 0) blk: { |
| 3923 | const fields_per_u32 = 32 / bits_per_field; | 3922 | const fields_per_u32 = 32 / bits_per_field; |
| 3924 | break :blk (field_count + fields_per_u32 - 1) / fields_per_u32; | 3923 | break :blk (field_count + fields_per_u32 - 1) / fields_per_u32; |
| 3925 | } else 0; | 3924 | } else 0; |
| 3926 | const payload_end = fields_start + field_count * max_field_size; | 3925 | const payload_end = fields_start + field_count * max_field_size; |
| 3927 | try payload.resize(gpa, payload_end); | 3926 | try payload.resize(gpa, payload_end); |
| 3928 | return Self{ | 3927 | return .{ |
| 3929 | .payload = payload, | 3928 | .payload = payload, |
| 3930 | .payload_top = payload_top, | 3929 | .payload_top = payload_top, |
| 3931 | .decls_start = decls_start, | ||
| 3932 | .field_bits_start = field_bits_start, | 3930 | .field_bits_start = field_bits_start, |
| 3933 | .fields_start = fields_start, | 3931 | .fields_start = fields_start, |
| 3934 | .decls_end = decls_start, | ||
| 3935 | .fields_end = fields_start, | 3932 | .fields_end = fields_start, |
| 3936 | }; | 3933 | }; |
| 3937 | } | 3934 | } |
| 3938 | 3935 | ||
| 3939 | fn nextDecl(self: *Self, is_pub: bool, is_export: bool, has_align: bool, has_section_or_addrspace: bool) void { | 3936 | fn nextDecl(self: *Self, decl_inst: Zir.Inst.Index) void { |
| 3940 | const index = self.payload_top + self.decl_index / decls_per_u32; | 3937 | self.payload.items[self.payload_top + self.decl_index] = @intFromEnum(decl_inst); |
| 3941 | assert(index < self.decls_start); | ||
| 3942 | const bit_bag: u32 = if (self.decl_index % decls_per_u32 == 0) 0 else self.payload.items[index]; | ||
| 3943 | self.payload.items[index] = (bit_bag >> bits_per_decl) | | ||
| 3944 | (@as(u32, @intFromBool(is_pub)) << 28) | | ||
| 3945 | (@as(u32, @intFromBool(is_export)) << 29) | | ||
| 3946 | (@as(u32, @intFromBool(has_align)) << 30) | | ||
| 3947 | (@as(u32, @intFromBool(has_section_or_addrspace)) << 31); | ||
| 3948 | self.decl_index += 1; | 3938 | self.decl_index += 1; |
| 3949 | } | 3939 | } |
| 3950 | 3940 | ||
| ... | @@ -3962,18 +3952,6 @@ const WipMembers = struct { | ... | @@ -3962,18 +3952,6 @@ const WipMembers = struct { |
| 3962 | self.field_index += 1; | 3952 | self.field_index += 1; |
| 3963 | } | 3953 | } |
| 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 | fn appendToField(self: *Self, data: u32) void { | 3955 | fn appendToField(self: *Self, data: u32) void { |
| 3978 | assert(self.fields_end < self.payload.items.len); | 3956 | assert(self.fields_end < self.payload.items.len); |
| 3979 | self.payload.items[self.fields_end] = data; | 3957 | self.payload.items[self.fields_end] = data; |
| ... | @@ -3981,11 +3959,6 @@ const WipMembers = struct { | ... | @@ -3981,11 +3959,6 @@ const WipMembers = struct { |
| 3981 | } | 3959 | } |
| 3982 | 3960 | ||
| 3983 | fn finishBits(self: *Self, comptime bits_per_field: u32) void { | 3961 | fn finishBits(self: *Self, comptime bits_per_field: u32) void { |
| 3984 | const empty_decl_slots = decls_per_u32 - (self.decl_index % decls_per_u32); | ||
| 3985 | if (self.decl_index > 0 and empty_decl_slots < decls_per_u32) { | ||
| 3986 | const index = self.payload_top + self.decl_index / decls_per_u32; | ||
| 3987 | self.payload.items[index] >>= @intCast(empty_decl_slots * bits_per_decl); | ||
| 3988 | } | ||
| 3989 | if (bits_per_field > 0) { | 3962 | if (bits_per_field > 0) { |
| 3990 | const fields_per_u32 = 32 / bits_per_field; | 3963 | const fields_per_u32 = 32 / bits_per_field; |
| 3991 | const empty_field_slots = fields_per_u32 - (self.field_index % fields_per_u32); | 3964 | const empty_field_slots = fields_per_u32 - (self.field_index % fields_per_u32); |
| ... | @@ -3997,7 +3970,7 @@ const WipMembers = struct { | ... | @@ -3997,7 +3970,7 @@ const WipMembers = struct { |
| 3997 | } | 3970 | } |
| 3998 | 3971 | ||
| 3999 | fn declsSlice(self: *Self) []u32 { | 3972 | fn declsSlice(self: *Self) []u32 { |
| 4000 | return self.payload.items[self.payload_top..self.decls_end]; | 3973 | return self.payload.items[self.payload_top..][0..self.decl_index]; |
| 4001 | } | 3974 | } |
| 4002 | 3975 | ||
| 4003 | fn fieldsSlice(self: *Self) []u32 { | 3976 | fn fieldsSlice(self: *Self) []u32 { |
| ... | @@ -4023,11 +3996,10 @@ fn fnDecl( | ... | @@ -4023,11 +3996,10 @@ fn fnDecl( |
| 4023 | 3996 | ||
| 4024 | // missing function name already happened in scanDecls() | 3997 | // missing function name already happened in scanDecls() |
| 4025 | const fn_name_token = fn_proto.name_token orelse return error.AnalysisFail; | 3998 | const fn_name_token = fn_proto.name_token orelse return error.AnalysisFail; |
| 4026 | const fn_name_str_index = try astgen.identAsString(fn_name_token); | ||
| 4027 | 3999 | ||
| 4028 | // We insert this at the beginning so that its instruction index marks the | 4000 | // We insert this at the beginning so that its instruction index marks the |
| 4029 | // start of the top level declaration. | 4001 | // start of the top level declaration. |
| 4030 | const block_inst = try gz.makeBlockInst(.block_inline, fn_proto.ast.proto_node); | 4002 | const decl_inst = try gz.makeBlockInst(.declaration, fn_proto.ast.proto_node); |
| 4031 | astgen.advanceSourceCursorToNode(decl_node); | 4003 | astgen.advanceSourceCursorToNode(decl_node); |
| 4032 | 4004 | ||
| 4033 | var decl_gz: GenZir = .{ | 4005 | var decl_gz: GenZir = .{ |
| ... | @@ -4072,8 +4044,7 @@ fn fnDecl( | ... | @@ -4072,8 +4044,7 @@ fn fnDecl( |
| 4072 | 4044 | ||
| 4073 | const doc_comment_index = try astgen.docCommentAsString(fn_proto.firstToken()); | 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. | 4047 | wip_members.nextDecl(decl_inst); |
| 4076 | wip_members.nextDecl(is_pub, is_export, false, false); | ||
| 4077 | 4048 | ||
| 4078 | var noalias_bits: u32 = 0; | 4049 | var noalias_bits: u32 = 0; |
| 4079 | var params_scope = &fn_gz.base; | 4050 | var params_scope = &fn_gz.base; |
| ... | @@ -4213,7 +4184,7 @@ fn fnDecl( | ... | @@ -4213,7 +4184,7 @@ fn fnDecl( |
| 4213 | var addrspace_gz = decl_gz.makeSubBlock(params_scope); | 4184 | var addrspace_gz = decl_gz.makeSubBlock(params_scope); |
| 4214 | defer addrspace_gz.unstack(); | 4185 | defer addrspace_gz.unstack(); |
| 4215 | const addrspace_ref: Zir.Inst.Ref = if (fn_proto.ast.addrspace_expr == 0) .none else inst: { | 4186 | const addrspace_ref: Zir.Inst.Ref = if (fn_proto.ast.addrspace_expr == 0) .none else inst: { |
| 4216 | const inst = try expr(&decl_gz, params_scope, .{ .rl = .{ .coerced_ty = .address_space_type } }, fn_proto.ast.addrspace_expr); | 4187 | const inst = try expr(&decl_gz, params_scope, addrspace_ri, fn_proto.ast.addrspace_expr); |
| 4217 | if (addrspace_gz.instructionsSlice().len == 0) { | 4188 | if (addrspace_gz.instructionsSlice().len == 0) { |
| 4218 | // In this case we will send a len=0 body which can be encoded more efficiently. | 4189 | // In this case we will send a len=0 body which can be encoded more efficiently. |
| 4219 | break :inst inst; | 4190 | break :inst inst; |
| ... | @@ -4298,7 +4269,7 @@ fn fnDecl( | ... | @@ -4298,7 +4269,7 @@ fn fnDecl( |
| 4298 | .section_gz = &section_gz, | 4269 | .section_gz = &section_gz, |
| 4299 | .addrspace_ref = addrspace_ref, | 4270 | .addrspace_ref = addrspace_ref, |
| 4300 | .addrspace_gz = &addrspace_gz, | 4271 | .addrspace_gz = &addrspace_gz, |
| 4301 | .param_block = block_inst, | 4272 | .param_block = decl_inst, |
| 4302 | .body_gz = null, | 4273 | .body_gz = null, |
| 4303 | .lib_name = lib_name, | 4274 | .lib_name = lib_name, |
| 4304 | .is_var_args = is_var_args, | 4275 | .is_var_args = is_var_args, |
| ... | @@ -4349,7 +4320,7 @@ fn fnDecl( | ... | @@ -4349,7 +4320,7 @@ fn fnDecl( |
| 4349 | .addrspace_gz = &addrspace_gz, | 4320 | .addrspace_gz = &addrspace_gz, |
| 4350 | .lbrace_line = lbrace_line, | 4321 | .lbrace_line = lbrace_line, |
| 4351 | .lbrace_column = lbrace_column, | 4322 | .lbrace_column = lbrace_column, |
| 4352 | .param_block = block_inst, | 4323 | .param_block = decl_inst, |
| 4353 | .body_gz = &fn_gz, | 4324 | .body_gz = &fn_gz, |
| 4354 | .lib_name = lib_name, | 4325 | .lib_name = lib_name, |
| 4355 | .is_var_args = is_var_args, | 4326 | .is_var_args = is_var_args, |
| ... | @@ -4363,20 +4334,21 @@ fn fnDecl( | ... | @@ -4363,20 +4334,21 @@ fn fnDecl( |
| 4363 | 4334 | ||
| 4364 | // We add this at the end so that its instruction index marks the end range | 4335 | // We add this at the end so that its instruction index marks the end range |
| 4365 | // of the top level declaration. addFunc already unstacked fn_gz and ret_gz. | 4336 | // of the top level declaration. addFunc already unstacked fn_gz and ret_gz. |
| 4366 | _ = try decl_gz.addBreak(.break_inline, block_inst, func_inst); | 4337 | _ = try decl_gz.addBreak(.break_inline, decl_inst, func_inst); |
| 4367 | try decl_gz.setBlockBody(block_inst); | 4338 | |
| 4368 | 4339 | try setDeclaration( | |
| 4369 | { | 4340 | decl_inst, |
| 4370 | const contents_hash align(@alignOf(u32)) = std.zig.hashSrc(tree.getNodeSource(decl_node)); | 4341 | std.zig.hashSrc(tree.getNodeSource(decl_node)), |
| 4371 | wip_members.appendToDeclSlice(std.mem.bytesAsSlice(u32, &contents_hash)); | 4342 | .{ .named = fn_name_token }, |
| 4372 | } | 4343 | decl_gz.decl_line - gz.decl_line, |
| 4373 | { | 4344 | is_pub, |
| 4374 | const line_delta = decl_gz.decl_line - gz.decl_line; | 4345 | is_export, |
| 4375 | wip_members.appendToDecl(line_delta); | 4346 | doc_comment_index, |
| 4376 | } | 4347 | &decl_gz, |
| 4377 | wip_members.appendToDecl(@intFromEnum(fn_name_str_index)); | 4348 | // align, linksection, and addrspace are passed in the func instruction in this case. |
| 4378 | wip_members.appendToDecl(@intFromEnum(block_inst)); | 4349 | // TODO: move them from the function instruction to the declaration instruction? |
| 4379 | wip_members.appendToDecl(@intFromEnum(doc_comment_index)); | 4350 | null, |
| 4351 | ); | ||
| 4380 | } | 4352 | } |
| 4381 | 4353 | ||
| 4382 | fn globalVarDecl( | 4354 | fn globalVarDecl( |
| ... | @@ -4393,10 +4365,9 @@ fn globalVarDecl( | ... | @@ -4393,10 +4365,9 @@ fn globalVarDecl( |
| 4393 | const is_mutable = token_tags[var_decl.ast.mut_token] == .keyword_var; | 4365 | const is_mutable = token_tags[var_decl.ast.mut_token] == .keyword_var; |
| 4394 | // We do this at the beginning so that the instruction index marks the range start | 4366 | // We do this at the beginning so that the instruction index marks the range start |
| 4395 | // of the top level declaration. | 4367 | // of the top level declaration. |
| 4396 | const block_inst = try gz.makeBlockInst(.block_inline, node); | 4368 | const decl_inst = try gz.makeBlockInst(.declaration, node); |
| 4397 | 4369 | ||
| 4398 | const name_token = var_decl.ast.mut_token + 1; | 4370 | const name_token = var_decl.ast.mut_token + 1; |
| 4399 | const name_str_index = try astgen.identAsString(name_token); | ||
| 4400 | astgen.advanceSourceCursorToNode(node); | 4371 | astgen.advanceSourceCursorToNode(node); |
| 4401 | 4372 | ||
| 4402 | var block_scope: GenZir = .{ | 4373 | var block_scope: GenZir = .{ |
| ... | @@ -4420,17 +4391,7 @@ fn globalVarDecl( | ... | @@ -4420,17 +4391,7 @@ fn globalVarDecl( |
| 4420 | const maybe_extern_token = var_decl.extern_export_token orelse break :blk false; | 4391 | const maybe_extern_token = var_decl.extern_export_token orelse break :blk false; |
| 4421 | break :blk token_tags[maybe_extern_token] == .keyword_extern; | 4392 | break :blk token_tags[maybe_extern_token] == .keyword_extern; |
| 4422 | }; | 4393 | }; |
| 4423 | const align_inst: Zir.Inst.Ref = if (var_decl.ast.align_node == 0) .none else inst: { | 4394 | wip_members.nextDecl(decl_inst); |
| 4424 | break :inst try expr(&block_scope, &block_scope.base, align_ri, var_decl.ast.align_node); | ||
| 4425 | }; | ||
| 4426 | const addrspace_inst: Zir.Inst.Ref = if (var_decl.ast.addrspace_node == 0) .none else inst: { | ||
| 4427 | break :inst try expr(&block_scope, &block_scope.base, .{ .rl = .{ .ty = .address_space_type } }, var_decl.ast.addrspace_node); | ||
| 4428 | }; | ||
| 4429 | const section_inst: Zir.Inst.Ref = if (var_decl.ast.section_node == 0) .none else inst: { | ||
| 4430 | break :inst try comptimeExpr(&block_scope, &block_scope.base, .{ .rl = .{ .ty = .slice_const_u8_type } }, var_decl.ast.section_node); | ||
| 4431 | }; | ||
| 4432 | const has_section_or_addrspace = section_inst != .none or addrspace_inst != .none; | ||
| 4433 | wip_members.nextDecl(is_pub, is_export, align_inst != .none, has_section_or_addrspace); | ||
| 4434 | 4395 | ||
| 4435 | const is_threadlocal = if (var_decl.threadlocal_token) |tok| blk: { | 4396 | const is_threadlocal = if (var_decl.threadlocal_token) |tok| blk: { |
| 4436 | if (!is_mutable) { | 4397 | if (!is_mutable) { |
| ... | @@ -4513,29 +4474,44 @@ fn globalVarDecl( | ... | @@ -4513,29 +4474,44 @@ fn globalVarDecl( |
| 4513 | } else { | 4474 | } else { |
| 4514 | return astgen.failNode(node, "unable to infer variable type", .{}); | 4475 | return astgen.failNode(node, "unable to infer variable type", .{}); |
| 4515 | }; | 4476 | }; |
| 4477 | |||
| 4516 | // We do this at the end so that the instruction index marks the end | 4478 | // We do this at the end so that the instruction index marks the end |
| 4517 | // range of a top level declaration. | 4479 | // range of a top level declaration. |
| 4518 | _ = try block_scope.addBreakWithSrcNode(.break_inline, block_inst, var_inst, node); | 4480 | _ = try block_scope.addBreakWithSrcNode(.break_inline, decl_inst, var_inst, node); |
| 4519 | try block_scope.setBlockBody(block_inst); | ||
| 4520 | 4481 | ||
| 4521 | { | 4482 | var align_gz = block_scope.makeSubBlock(scope); |
| 4522 | const contents_hash align(@alignOf(u32)) = std.zig.hashSrc(tree.getNodeSource(node)); | 4483 | if (var_decl.ast.align_node != 0) { |
| 4523 | wip_members.appendToDeclSlice(std.mem.bytesAsSlice(u32, &contents_hash)); | 4484 | const align_inst = try expr(&align_gz, &align_gz.base, coerced_align_ri, var_decl.ast.align_node); |
| 4485 | _ = try align_gz.addBreakWithSrcNode(.break_inline, decl_inst, align_inst, node); | ||
| 4524 | } | 4486 | } |
| 4525 | { | 4487 | |
| 4526 | const line_delta = block_scope.decl_line - gz.decl_line; | 4488 | var linksection_gz = align_gz.makeSubBlock(scope); |
| 4527 | wip_members.appendToDecl(line_delta); | 4489 | if (var_decl.ast.section_node != 0) { |
| 4528 | } | 4490 | const linksection_inst = try expr(&linksection_gz, &linksection_gz.base, coerced_linksection_ri, var_decl.ast.section_node); |
| 4529 | wip_members.appendToDecl(@intFromEnum(name_str_index)); | 4491 | _ = try linksection_gz.addBreakWithSrcNode(.break_inline, decl_inst, linksection_inst, node); |
| 4530 | wip_members.appendToDecl(@intFromEnum(block_inst)); | ||
| 4531 | wip_members.appendToDecl(@intFromEnum(doc_comment_index)); // doc_comment wip | ||
| 4532 | if (align_inst != .none) { | ||
| 4533 | wip_members.appendToDecl(@intFromEnum(align_inst)); | ||
| 4534 | } | ||
| 4535 | if (has_section_or_addrspace) { | ||
| 4536 | wip_members.appendToDecl(@intFromEnum(section_inst)); | ||
| 4537 | wip_members.appendToDecl(@intFromEnum(addrspace_inst)); | ||
| 4538 | } | 4492 | } |
| 4493 | |||
| 4494 | var addrspace_gz = linksection_gz.makeSubBlock(scope); | ||
| 4495 | if (var_decl.ast.addrspace_node != 0) { | ||
| 4496 | const addrspace_inst = try expr(&addrspace_gz, &addrspace_gz.base, coerced_addrspace_ri, var_decl.ast.addrspace_node); | ||
| 4497 | _ = try addrspace_gz.addBreakWithSrcNode(.break_inline, decl_inst, addrspace_inst, node); | ||
| 4498 | } | ||
| 4499 | |||
| 4500 | try setDeclaration( | ||
| 4501 | decl_inst, | ||
| 4502 | std.zig.hashSrc(tree.getNodeSource(node)), | ||
| 4503 | .{ .named = name_token }, | ||
| 4504 | block_scope.decl_line - gz.decl_line, | ||
| 4505 | is_pub, | ||
| 4506 | is_export, | ||
| 4507 | doc_comment_index, | ||
| 4508 | &block_scope, | ||
| 4509 | .{ | ||
| 4510 | .align_gz = &align_gz, | ||
| 4511 | .linksection_gz = &linksection_gz, | ||
| 4512 | .addrspace_gz = &addrspace_gz, | ||
| 4513 | }, | ||
| 4514 | ); | ||
| 4539 | } | 4515 | } |
| 4540 | 4516 | ||
| 4541 | fn comptimeDecl( | 4517 | fn comptimeDecl( |
| ... | @@ -4551,8 +4527,8 @@ fn comptimeDecl( | ... | @@ -4551,8 +4527,8 @@ fn comptimeDecl( |
| 4551 | 4527 | ||
| 4552 | // Up top so the ZIR instruction index marks the start range of this | 4528 | // Up top so the ZIR instruction index marks the start range of this |
| 4553 | // top-level declaration. | 4529 | // top-level declaration. |
| 4554 | const block_inst = try gz.makeBlockInst(.block_inline, node); | 4530 | const decl_inst = try gz.makeBlockInst(.declaration, node); |
| 4555 | wip_members.nextDecl(false, false, false, false); | 4531 | wip_members.nextDecl(decl_inst); |
| 4556 | astgen.advanceSourceCursorToNode(node); | 4532 | astgen.advanceSourceCursorToNode(node); |
| 4557 | 4533 | ||
| 4558 | var decl_block: GenZir = .{ | 4534 | var decl_block: GenZir = .{ |
| ... | @@ -4568,21 +4544,20 @@ fn comptimeDecl( | ... | @@ -4568,21 +4544,20 @@ fn comptimeDecl( |
| 4568 | 4544 | ||
| 4569 | const block_result = try expr(&decl_block, &decl_block.base, .{ .rl = .none }, body_node); | 4545 | const block_result = try expr(&decl_block, &decl_block.base, .{ .rl = .none }, body_node); |
| 4570 | if (decl_block.isEmpty() or !decl_block.refIsNoReturn(block_result)) { | 4546 | if (decl_block.isEmpty() or !decl_block.refIsNoReturn(block_result)) { |
| 4571 | _ = try decl_block.addBreak(.break_inline, block_inst, .void_value); | 4547 | _ = try decl_block.addBreak(.break_inline, decl_inst, .void_value); |
| 4572 | } | 4548 | } |
| 4573 | try decl_block.setBlockBody(block_inst); | ||
| 4574 | 4549 | ||
| 4575 | { | 4550 | try setDeclaration( |
| 4576 | const contents_hash align(@alignOf(u32)) = std.zig.hashSrc(tree.getNodeSource(node)); | 4551 | decl_inst, |
| 4577 | wip_members.appendToDeclSlice(std.mem.bytesAsSlice(u32, &contents_hash)); | 4552 | std.zig.hashSrc(tree.getNodeSource(node)), |
| 4578 | } | 4553 | .@"comptime", |
| 4579 | { | 4554 | decl_block.decl_line - gz.decl_line, |
| 4580 | const line_delta = decl_block.decl_line - gz.decl_line; | 4555 | false, |
| 4581 | wip_members.appendToDecl(line_delta); | 4556 | false, |
| 4582 | } | 4557 | .empty, |
| 4583 | wip_members.appendToDecl(0); | 4558 | &decl_block, |
| 4584 | wip_members.appendToDecl(@intFromEnum(block_inst)); | 4559 | null, |
| 4585 | wip_members.appendToDecl(0); // no doc comments on comptime decls | 4560 | ); |
| 4586 | } | 4561 | } |
| 4587 | 4562 | ||
| 4588 | fn usingnamespaceDecl( | 4563 | fn usingnamespaceDecl( |
| ... | @@ -4604,8 +4579,8 @@ fn usingnamespaceDecl( | ... | @@ -4604,8 +4579,8 @@ fn usingnamespaceDecl( |
| 4604 | }; | 4579 | }; |
| 4605 | // Up top so the ZIR instruction index marks the start range of this | 4580 | // Up top so the ZIR instruction index marks the start range of this |
| 4606 | // top-level declaration. | 4581 | // top-level declaration. |
| 4607 | const block_inst = try gz.makeBlockInst(.block_inline, node); | 4582 | const decl_inst = try gz.makeBlockInst(.declaration, node); |
| 4608 | wip_members.nextDecl(is_pub, true, false, false); | 4583 | wip_members.nextDecl(decl_inst); |
| 4609 | astgen.advanceSourceCursorToNode(node); | 4584 | astgen.advanceSourceCursorToNode(node); |
| 4610 | 4585 | ||
| 4611 | var decl_block: GenZir = .{ | 4586 | var decl_block: GenZir = .{ |
| ... | @@ -4620,20 +4595,19 @@ fn usingnamespaceDecl( | ... | @@ -4620,20 +4595,19 @@ fn usingnamespaceDecl( |
| 4620 | defer decl_block.unstack(); | 4595 | defer decl_block.unstack(); |
| 4621 | 4596 | ||
| 4622 | const namespace_inst = try typeExpr(&decl_block, &decl_block.base, type_expr); | 4597 | const namespace_inst = try typeExpr(&decl_block, &decl_block.base, type_expr); |
| 4623 | _ = try decl_block.addBreak(.break_inline, block_inst, namespace_inst); | 4598 | _ = try decl_block.addBreak(.break_inline, decl_inst, namespace_inst); |
| 4624 | try decl_block.setBlockBody(block_inst); | 4599 | |
| 4625 | 4600 | try setDeclaration( | |
| 4626 | { | 4601 | decl_inst, |
| 4627 | const contents_hash align(@alignOf(u32)) = std.zig.hashSrc(tree.getNodeSource(node)); | 4602 | std.zig.hashSrc(tree.getNodeSource(node)), |
| 4628 | wip_members.appendToDeclSlice(std.mem.bytesAsSlice(u32, &contents_hash)); | 4603 | .@"usingnamespace", |
| 4629 | } | 4604 | decl_block.decl_line - gz.decl_line, |
| 4630 | { | 4605 | is_pub, |
| 4631 | const line_delta = decl_block.decl_line - gz.decl_line; | 4606 | false, |
| 4632 | wip_members.appendToDecl(line_delta); | 4607 | .empty, |
| 4633 | } | 4608 | &decl_block, |
| 4634 | wip_members.appendToDecl(0); | 4609 | null, |
| 4635 | wip_members.appendToDecl(@intFromEnum(block_inst)); | 4610 | ); |
| 4636 | wip_members.appendToDecl(0); // no doc comments on usingnamespace decls | ||
| 4637 | } | 4611 | } |
| 4638 | 4612 | ||
| 4639 | fn testDecl( | 4613 | fn testDecl( |
| ... | @@ -4649,9 +4623,9 @@ fn testDecl( | ... | @@ -4649,9 +4623,9 @@ fn testDecl( |
| 4649 | 4623 | ||
| 4650 | // Up top so the ZIR instruction index marks the start range of this | 4624 | // Up top so the ZIR instruction index marks the start range of this |
| 4651 | // top-level declaration. | 4625 | // top-level declaration. |
| 4652 | const block_inst = try gz.makeBlockInst(.block_inline, node); | 4626 | const decl_inst = try gz.makeBlockInst(.declaration, node); |
| 4653 | 4627 | ||
| 4654 | wip_members.nextDecl(false, false, false, false); | 4628 | wip_members.nextDecl(decl_inst); |
| 4655 | astgen.advanceSourceCursorToNode(node); | 4629 | astgen.advanceSourceCursorToNode(node); |
| 4656 | 4630 | ||
| 4657 | var decl_block: GenZir = .{ | 4631 | var decl_block: GenZir = .{ |
| ... | @@ -4669,12 +4643,10 @@ fn testDecl( | ... | @@ -4669,12 +4643,10 @@ fn testDecl( |
| 4669 | const token_tags = tree.tokens.items(.tag); | 4643 | const token_tags = tree.tokens.items(.tag); |
| 4670 | const test_token = main_tokens[node]; | 4644 | const test_token = main_tokens[node]; |
| 4671 | const test_name_token = test_token + 1; | 4645 | const test_name_token = test_token + 1; |
| 4672 | const test_name_token_tag = token_tags[test_name_token]; | 4646 | const test_name: DeclarationName = switch (token_tags[test_name_token]) { |
| 4673 | const is_decltest = test_name_token_tag == .identifier; | 4647 | else => .unnamed_test, |
| 4674 | const test_name: Zir.NullTerminatedString = blk: { | 4648 | .string_literal => .{ .named_test = test_name_token }, |
| 4675 | if (test_name_token_tag == .string_literal) { | 4649 | .identifier => blk: { |
| 4676 | break :blk try astgen.testNameString(test_name_token); | ||
| 4677 | } else if (test_name_token_tag == .identifier) { | ||
| 4678 | const ident_name_raw = tree.tokenSlice(test_name_token); | 4650 | const ident_name_raw = tree.tokenSlice(test_name_token); |
| 4679 | 4651 | ||
| 4680 | if (mem.eql(u8, ident_name_raw, "_")) return astgen.failTok(test_name_token, "'_' used as an identifier without @\"_\" syntax", .{}); | 4652 | if (mem.eql(u8, ident_name_raw, "_")) return astgen.failTok(test_name_token, "'_' used as an identifier without @\"_\" syntax", .{}); |
| ... | @@ -4744,10 +4716,8 @@ fn testDecl( | ... | @@ -4744,10 +4716,8 @@ fn testDecl( |
| 4744 | return astgen.failTok(test_name_token, "use of undeclared identifier '{s}'", .{ident_name}); | 4716 | return astgen.failTok(test_name_token, "use of undeclared identifier '{s}'", .{ident_name}); |
| 4745 | } | 4717 | } |
| 4746 | 4718 | ||
| 4747 | break :blk name_str_index; | 4719 | break :blk .{ .decltest = name_str_index }; |
| 4748 | } | 4720 | }, |
| 4749 | // String table index 1 has a special meaning here of test decl with no name. | ||
| 4750 | break :blk .unnamed_test_decl; | ||
| 4751 | }; | 4721 | }; |
| 4752 | 4722 | ||
| 4753 | var fn_block: GenZir = .{ | 4723 | var fn_block: GenZir = .{ |
| ... | @@ -4795,7 +4765,7 @@ fn testDecl( | ... | @@ -4795,7 +4765,7 @@ fn testDecl( |
| 4795 | 4765 | ||
| 4796 | .lbrace_line = lbrace_line, | 4766 | .lbrace_line = lbrace_line, |
| 4797 | .lbrace_column = lbrace_column, | 4767 | .lbrace_column = lbrace_column, |
| 4798 | .param_block = block_inst, | 4768 | .param_block = decl_inst, |
| 4799 | .body_gz = &fn_block, | 4769 | .body_gz = &fn_block, |
| 4800 | .lib_name = .empty, | 4770 | .lib_name = .empty, |
| 4801 | .is_var_args = false, | 4771 | .is_var_args = false, |
| ... | @@ -4806,26 +4776,19 @@ fn testDecl( | ... | @@ -4806,26 +4776,19 @@ fn testDecl( |
| 4806 | .noalias_bits = 0, | 4776 | .noalias_bits = 0, |
| 4807 | }); | 4777 | }); |
| 4808 | 4778 | ||
| 4809 | _ = try decl_block.addBreak(.break_inline, block_inst, func_inst); | 4779 | _ = try decl_block.addBreak(.break_inline, decl_inst, func_inst); |
| 4810 | try decl_block.setBlockBody(block_inst); | 4780 | |
| 4811 | 4781 | try setDeclaration( | |
| 4812 | { | 4782 | decl_inst, |
| 4813 | const contents_hash align(@alignOf(u32)) = std.zig.hashSrc(tree.getNodeSource(node)); | 4783 | std.zig.hashSrc(tree.getNodeSource(node)), |
| 4814 | wip_members.appendToDeclSlice(std.mem.bytesAsSlice(u32, &contents_hash)); | 4784 | test_name, |
| 4815 | } | 4785 | decl_block.decl_line - gz.decl_line, |
| 4816 | { | 4786 | false, |
| 4817 | const line_delta = decl_block.decl_line - gz.decl_line; | 4787 | false, |
| 4818 | wip_members.appendToDecl(line_delta); | 4788 | .empty, |
| 4819 | } | 4789 | &decl_block, |
| 4820 | if (is_decltest) | 4790 | null, |
| 4821 | wip_members.appendToDecl(2) // 2 here means that it is a decltest, look at doc comment for name | 4791 | ); |
| 4822 | else | ||
| 4823 | wip_members.appendToDecl(@intFromEnum(test_name)); | ||
| 4824 | wip_members.appendToDecl(@intFromEnum(block_inst)); | ||
| 4825 | if (is_decltest) | ||
| 4826 | wip_members.appendToDecl(@intFromEnum(test_name)) // the doc comment on a decltest represents it's name | ||
| 4827 | else | ||
| 4828 | wip_members.appendToDecl(0); // no doc comments on test decls | ||
| 4829 | } | 4792 | } |
| 4830 | 4793 | ||
| 4831 | fn structDeclInner( | 4794 | fn structDeclInner( |
| ... | @@ -13524,3 +13487,106 @@ fn lowerAstErrors(astgen: *AstGen) !void { | ... | @@ -13524,3 +13487,106 @@ fn lowerAstErrors(astgen: *AstGen) !void { |
| 13524 | try tree.renderError(parse_err, msg.writer(gpa)); | 13487 | try tree.renderError(parse_err, msg.writer(gpa)); |
| 13525 | try astgen.appendErrorTokNotesOff(parse_err.token, extra_offset, "{s}", .{msg.items}, notes.items); | 13488 | try astgen.appendErrorTokNotesOff(parse_err.token, extra_offset, "{s}", .{msg.items}, notes.items); |
| 13526 | } | 13489 | } |
| 13490 | |||
| 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,22 +2846,14 @@ fn walkInstruction( |
| 2846 | return res; | 2846 | return res; |
| 2847 | }, | 2847 | }, |
| 2848 | .block_inline => { | 2848 | .block_inline => { |
| 2849 | return self.walkRef( | 2849 | const pl_node = data[@intFromEnum(inst)].pl_node; |
| 2850 | const extra = file.zir.extraData(Zir.Inst.Block, pl_node.payload_index); | ||
| 2851 | return self.walkInlineBody( | ||
| 2850 | file, | 2852 | file, |
| 2851 | parent_scope, | 2853 | parent_scope, |
| 2854 | try self.srcLocInfo(file, pl_node.src_node, parent_src), | ||
| 2852 | parent_src, | 2855 | parent_src, |
| 2853 | getBlockInlineBreak(file.zir, inst) orelse { | 2856 | file.zir.bodySlice(extra.end, extra.data.body_len), |
| 2854 | const res = DocData.WalkResult{ | ||
| 2855 | .typeRef = .{ .type = @intFromEnum(Ref.type_type) }, | ||
| 2856 | .expr = .{ .comptimeExpr = self.comptime_exprs.items.len }, | ||
| 2857 | }; | ||
| 2858 | const pl_node = data[@intFromEnum(inst)].pl_node; | ||
| 2859 | const block_inline_expr = try self.getBlockSource(file, parent_src, pl_node.src_node); | ||
| 2860 | try self.comptime_exprs.append(self.arena, .{ | ||
| 2861 | .code = block_inline_expr, | ||
| 2862 | }); | ||
| 2863 | return res; | ||
| 2864 | }, | ||
| 2865 | need_type, | 2857 | need_type, |
| 2866 | call_ctx, | 2858 | call_ctx, |
| 2867 | ); | 2859 | ); |
| ... | @@ -4084,19 +4076,11 @@ fn analyzeAllDecls( | ... | @@ -4084,19 +4076,11 @@ fn analyzeAllDecls( |
| 4084 | // First loop to discover decl names | 4076 | // First loop to discover decl names |
| 4085 | { | 4077 | { |
| 4086 | var it = original_it; | 4078 | var it = original_it; |
| 4087 | while (it.next()) |d| { | 4079 | while (it.next()) |zir_index| { |
| 4088 | const decl_name_index: Zir.NullTerminatedString = @enumFromInt(file.zir.extra[@intFromEnum(d.sub_index) + 5]); | 4080 | const declaration, _ = file.zir.getDeclaration(zir_index); |
| 4089 | switch (decl_name_index) { | 4081 | if (declaration.name.isNamedTest(file.zir)) continue; |
| 4090 | .empty, | 4082 | const decl_name = declaration.name.toString(file.zir) orelse continue; |
| 4091 | .unnamed_test_decl, | 4083 | try scope.insertDeclRef(self.arena, decl_name, .Pending); |
| 4092 | .decltest, | ||
| 4093 | => continue, | ||
| 4094 | _ => if (file.zir.nullTerminatedString(decl_name_index).len == 0) { | ||
| 4095 | continue; | ||
| 4096 | }, | ||
| 4097 | } | ||
| 4098 | |||
| 4099 | try scope.insertDeclRef(self.arena, decl_name_index, .Pending); | ||
| 4100 | } | 4084 | } |
| 4101 | } | 4085 | } |
| 4102 | 4086 | ||
| ... | @@ -4104,147 +4088,114 @@ fn analyzeAllDecls( | ... | @@ -4104,147 +4088,114 @@ fn analyzeAllDecls( |
| 4104 | { | 4088 | { |
| 4105 | var it = original_it; | 4089 | var it = original_it; |
| 4106 | var decl_indexes_slot = first_decl_indexes_slot; | 4090 | var decl_indexes_slot = first_decl_indexes_slot; |
| 4107 | while (it.next()) |d| : (decl_indexes_slot += 1) { | 4091 | while (it.next()) |zir_index| : (decl_indexes_slot += 1) { |
| 4108 | const decl_name_index = file.zir.extra[@intFromEnum(d.sub_index) + 5]; | 4092 | const pl_node = file.zir.instructions.items(.data)[@intFromEnum(zir_index)].pl_node; |
| 4109 | switch (decl_name_index) { | 4093 | const extra = file.zir.extraData(Zir.Inst.Declaration, pl_node.payload_index); |
| 4110 | 0 => { | 4094 | if (extra.data.name != .@"usingnamespace") continue; |
| 4111 | const is_exported = @as(u1, @truncate(d.flags >> 1)); | 4095 | try self.analyzeUsingnamespaceDecl( |
| 4112 | switch (is_exported) { | 4096 | file, |
| 4113 | 0 => continue, // comptime decl | 4097 | scope, |
| 4114 | 1 => { | 4098 | try self.srcLocInfo(file, pl_node.src_node, parent_src), |
| 4115 | try self.analyzeUsingnamespaceDecl( | 4099 | decl_indexes, |
| 4116 | file, | 4100 | priv_decl_indexes, |
| 4117 | scope, | 4101 | extra.data, |
| 4118 | parent_src, | 4102 | @intCast(extra.end), |
| 4119 | decl_indexes, | 4103 | call_ctx, |
| 4120 | priv_decl_indexes, | 4104 | ); |
| 4121 | d, | ||
| 4122 | call_ctx, | ||
| 4123 | ); | ||
| 4124 | }, | ||
| 4125 | } | ||
| 4126 | }, | ||
| 4127 | else => continue, | ||
| 4128 | } | ||
| 4129 | } | 4105 | } |
| 4130 | } | 4106 | } |
| 4131 | 4107 | ||
| 4132 | // Third loop to analyze all remaining decls | 4108 | // Third loop to analyze all remaining decls |
| 4133 | var it = original_it; | 4109 | { |
| 4134 | while (it.next()) |d| { | 4110 | var it = original_it; |
| 4135 | const decl_name_index = file.zir.extra[@intFromEnum(d.sub_index) + 5]; | 4111 | while (it.next()) |zir_index| { |
| 4136 | switch (decl_name_index) { | 4112 | const pl_node = file.zir.instructions.items(.data)[@intFromEnum(zir_index)].pl_node; |
| 4137 | 0, 1 => continue, // skip over usingnamespace decls | 4113 | const extra = file.zir.extraData(Zir.Inst.Declaration, pl_node.payload_index); |
| 4138 | 2 => continue, // skip decltests | 4114 | switch (extra.data.name) { |
| 4139 | 4115 | .@"comptime", .@"usingnamespace", .unnamed_test, .decltest => continue, | |
| 4140 | else => if (file.zir.string_bytes[decl_name_index] == 0) { | 4116 | _ => if (extra.data.name.isNamedTest(file.zir)) continue, |
| 4141 | continue; | 4117 | } |
| 4142 | }, | 4118 | try self.analyzeDecl( |
| 4119 | file, | ||
| 4120 | scope, | ||
| 4121 | try self.srcLocInfo(file, pl_node.src_node, parent_src), | ||
| 4122 | decl_indexes, | ||
| 4123 | priv_decl_indexes, | ||
| 4124 | zir_index, | ||
| 4125 | extra.data, | ||
| 4126 | @intCast(extra.end), | ||
| 4127 | call_ctx, | ||
| 4128 | ); | ||
| 4143 | } | 4129 | } |
| 4144 | |||
| 4145 | try self.analyzeDecl( | ||
| 4146 | file, | ||
| 4147 | scope, | ||
| 4148 | parent_src, | ||
| 4149 | decl_indexes, | ||
| 4150 | priv_decl_indexes, | ||
| 4151 | d, | ||
| 4152 | call_ctx, | ||
| 4153 | ); | ||
| 4154 | } | 4130 | } |
| 4155 | 4131 | ||
| 4156 | // Fourth loop to analyze decltests | 4132 | // Fourth loop to analyze decltests |
| 4157 | it = original_it; | 4133 | var it = original_it; |
| 4158 | while (it.next()) |d| { | 4134 | while (it.next()) |zir_index| { |
| 4159 | const decl_name_index = file.zir.extra[@intFromEnum(d.sub_index) + 5]; | 4135 | const pl_node = file.zir.instructions.items(.data)[@intFromEnum(zir_index)].pl_node; |
| 4160 | switch (decl_name_index) { | 4136 | const extra = file.zir.extraData(Zir.Inst.Declaration, pl_node.payload_index); |
| 4161 | 0, 1 => continue, // skip over usingnamespace decls | 4137 | if (extra.data.name != .decltest) continue; |
| 4162 | 2 => {}, | ||
| 4163 | else => continue, // skip tests and normal decls | ||
| 4164 | } | ||
| 4165 | |||
| 4166 | try self.analyzeDecltest( | 4138 | try self.analyzeDecltest( |
| 4167 | file, | 4139 | file, |
| 4168 | scope, | 4140 | scope, |
| 4169 | parent_src, | 4141 | try self.srcLocInfo(file, pl_node.src_node, parent_src), |
| 4170 | d, | 4142 | extra.data, |
| 4143 | @intCast(extra.end), | ||
| 4171 | ); | 4144 | ); |
| 4172 | } | 4145 | } |
| 4173 | 4146 | ||
| 4174 | return it.extra_index; | 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 | // Asserts the given decl is public | 4181 | // Asserts the given decl is public |
| 4178 | fn analyzeDecl( | 4182 | fn analyzeDecl( |
| 4179 | self: *Autodoc, | 4183 | self: *Autodoc, |
| 4180 | file: *File, | 4184 | file: *File, |
| 4181 | scope: *Scope, | 4185 | scope: *Scope, |
| 4182 | parent_src: SrcLocInfo, | 4186 | decl_src: SrcLocInfo, |
| 4183 | decl_indexes: *std.ArrayListUnmanaged(usize), | 4187 | decl_indexes: *std.ArrayListUnmanaged(usize), |
| 4184 | priv_decl_indexes: *std.ArrayListUnmanaged(usize), | 4188 | priv_decl_indexes: *std.ArrayListUnmanaged(usize), |
| 4185 | d: Zir.DeclIterator.Item, | 4189 | decl_inst: Zir.Inst.Index, |
| 4190 | declaration: Zir.Inst.Declaration, | ||
| 4191 | extra_index: u32, | ||
| 4186 | call_ctx: ?*const CallContext, | 4192 | call_ctx: ?*const CallContext, |
| 4187 | ) AutodocErrors!void { | 4193 | ) AutodocErrors!void { |
| 4188 | const data = file.zir.instructions.items(.data); | 4194 | const bodies = declaration.getBodies(extra_index, file.zir); |
| 4189 | const is_pub = @as(u1, @truncate(d.flags >> 0)) != 0; | 4195 | const name = file.zir.nullTerminatedString(declaration.name.toString(file.zir).?); |
| 4190 | // const is_exported = @truncate(u1, d.flags >> 1) != 0; | ||
| 4191 | const has_align = @as(u1, @truncate(d.flags >> 2)) != 0; | ||
| 4192 | const has_section_or_addrspace = @as(u1, @truncate(d.flags >> 3)) != 0; | ||
| 4193 | |||
| 4194 | var extra_index = @intFromEnum(d.sub_index); | ||
| 4195 | // const hash_u32s = file.zir.extra[extra_index..][0..4]; | ||
| 4196 | |||
| 4197 | extra_index += 4; | ||
| 4198 | // const line = file.zir.extra[extra_index]; | ||
| 4199 | |||
| 4200 | extra_index += 1; | ||
| 4201 | const decl_name_index: Zir.NullTerminatedString = @enumFromInt(file.zir.extra[extra_index]); | ||
| 4202 | |||
| 4203 | extra_index += 1; | ||
| 4204 | const value_index: Zir.Inst.Index = @enumFromInt(file.zir.extra[extra_index]); | ||
| 4205 | |||
| 4206 | extra_index += 1; | ||
| 4207 | const doc_comment_index: Zir.NullTerminatedString = @enumFromInt(file.zir.extra[extra_index]); | ||
| 4208 | |||
| 4209 | extra_index += 1; | ||
| 4210 | const align_inst: Zir.Inst.Ref = if (!has_align) .none else inst: { | ||
| 4211 | const inst: Zir.Inst.Ref = @enumFromInt(file.zir.extra[extra_index]); | ||
| 4212 | extra_index += 1; | ||
| 4213 | break :inst inst; | ||
| 4214 | }; | ||
| 4215 | _ = align_inst; | ||
| 4216 | |||
| 4217 | const section_inst: Zir.Inst.Ref = if (!has_section_or_addrspace) .none else inst: { | ||
| 4218 | const inst: Zir.Inst.Ref = @enumFromInt(file.zir.extra[extra_index]); | ||
| 4219 | extra_index += 1; | ||
| 4220 | break :inst inst; | ||
| 4221 | }; | ||
| 4222 | _ = section_inst; | ||
| 4223 | 4196 | ||
| 4224 | const addrspace_inst: Zir.Inst.Ref = if (!has_section_or_addrspace) .none else inst: { | 4197 | const doc_comment: ?[]const u8 = if (declaration.flags.has_doc_comment) |
| 4225 | const inst: Zir.Inst.Ref = @enumFromInt(file.zir.extra[extra_index]); | 4198 | file.zir.nullTerminatedString(@enumFromInt(file.zir.extra[extra_index])) |
| 4226 | extra_index += 1; | ||
| 4227 | break :inst inst; | ||
| 4228 | }; | ||
| 4229 | _ = addrspace_inst; | ||
| 4230 | |||
| 4231 | // This is known to work because decl values are always block_inlines | ||
| 4232 | const value_pl_node = data[@intFromEnum(value_index)].pl_node; | ||
| 4233 | const decl_src = try self.srcLocInfo(file, value_pl_node.src_node, parent_src); | ||
| 4234 | |||
| 4235 | const name: []const u8 = switch (decl_name_index) { | ||
| 4236 | .empty, .unnamed_test_decl, .decltest => unreachable, | ||
| 4237 | _ => blk: { | ||
| 4238 | if (decl_name_index == .empty) { | ||
| 4239 | // test decl | ||
| 4240 | unreachable; | ||
| 4241 | } | ||
| 4242 | break :blk file.zir.nullTerminatedString(decl_name_index); | ||
| 4243 | }, | ||
| 4244 | }; | ||
| 4245 | |||
| 4246 | const doc_comment: ?[]const u8 = if (doc_comment_index != .empty) | ||
| 4247 | file.zir.nullTerminatedString(doc_comment_index) | ||
| 4248 | else | 4199 | else |
| 4249 | null; | 4200 | null; |
| 4250 | 4201 | ||
| ... | @@ -4261,16 +4212,22 @@ fn analyzeDecl( | ... | @@ -4261,16 +4212,22 @@ fn analyzeDecl( |
| 4261 | break :idx idx; | 4212 | break :idx idx; |
| 4262 | }; | 4213 | }; |
| 4263 | 4214 | ||
| 4264 | const walk_result = try self.walkInstruction( | 4215 | const walk_result = try self.walkInlineBody( |
| 4265 | file, | 4216 | file, |
| 4266 | scope, | 4217 | scope, |
| 4267 | decl_src, | 4218 | decl_src, |
| 4268 | value_index, | 4219 | decl_src, |
| 4220 | bodies.value_body, | ||
| 4269 | true, | 4221 | true, |
| 4270 | call_ctx, | 4222 | call_ctx, |
| 4271 | ); | 4223 | ); |
| 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 | const decls_slot_index = self.decls.items.len; | 4232 | const decls_slot_index = self.decls.items.len; |
| 4276 | try self.decls.append(self.arena, .{ | 4233 | try self.decls.append(self.arena, .{ |
| ... | @@ -4281,13 +4238,13 @@ fn analyzeDecl( | ... | @@ -4281,13 +4238,13 @@ fn analyzeDecl( |
| 4281 | .parent_container = scope.enclosing_type, | 4238 | .parent_container = scope.enclosing_type, |
| 4282 | }); | 4239 | }); |
| 4283 | 4240 | ||
| 4284 | if (is_pub) { | 4241 | if (declaration.flags.is_pub) { |
| 4285 | try decl_indexes.append(self.arena, decls_slot_index); | 4242 | try decl_indexes.append(self.arena, decls_slot_index); |
| 4286 | } else { | 4243 | } else { |
| 4287 | try priv_decl_indexes.append(self.arena, decls_slot_index); | 4244 | try priv_decl_indexes.append(self.arena, decls_slot_index); |
| 4288 | } | 4245 | } |
| 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 | std.debug.assert(decl_status_ptr.* == .Pending); | 4248 | std.debug.assert(decl_status_ptr.* == .Pending); |
| 4292 | decl_status_ptr.* = .{ .Analyzed = decls_slot_index }; | 4249 | decl_status_ptr.* = .{ .Analyzed = decls_slot_index }; |
| 4293 | 4250 | ||
| ... | @@ -4296,7 +4253,7 @@ fn analyzeDecl( | ... | @@ -4296,7 +4253,7 @@ fn analyzeDecl( |
| 4296 | for (paths.items) |resume_info| { | 4253 | for (paths.items) |resume_info| { |
| 4297 | try self.tryResolveRefPath( | 4254 | try self.tryResolveRefPath( |
| 4298 | resume_info.file, | 4255 | resume_info.file, |
| 4299 | value_index, | 4256 | decl_inst, |
| 4300 | resume_info.ref_path, | 4257 | resume_info.ref_path, |
| 4301 | ); | 4258 | ); |
| 4302 | } | 4259 | } |
| ... | @@ -4312,24 +4269,17 @@ fn analyzeUsingnamespaceDecl( | ... | @@ -4312,24 +4269,17 @@ fn analyzeUsingnamespaceDecl( |
| 4312 | self: *Autodoc, | 4269 | self: *Autodoc, |
| 4313 | file: *File, | 4270 | file: *File, |
| 4314 | scope: *Scope, | 4271 | scope: *Scope, |
| 4315 | parent_src: SrcLocInfo, | 4272 | decl_src: SrcLocInfo, |
| 4316 | decl_indexes: *std.ArrayListUnmanaged(usize), | 4273 | decl_indexes: *std.ArrayListUnmanaged(usize), |
| 4317 | priv_decl_indexes: *std.ArrayListUnmanaged(usize), | 4274 | priv_decl_indexes: *std.ArrayListUnmanaged(usize), |
| 4318 | d: Zir.DeclIterator.Item, | 4275 | declaration: Zir.Inst.Declaration, |
| 4276 | extra_index: u32, | ||
| 4319 | call_ctx: ?*const CallContext, | 4277 | call_ctx: ?*const CallContext, |
| 4320 | ) AutodocErrors!void { | 4278 | ) AutodocErrors!void { |
| 4321 | const data = file.zir.instructions.items(.data); | 4279 | const bodies = declaration.getBodies(extra_index, file.zir); |
| 4322 | 4280 | ||
| 4323 | const is_pub = @as(u1, @truncate(d.flags)) != 0; | 4281 | const doc_comment: ?[]const u8 = if (declaration.flags.has_doc_comment) |
| 4324 | const value_index: Zir.Inst.Index = @enumFromInt(file.zir.extra[@intFromEnum(d.sub_index) + 6]); | 4282 | file.zir.nullTerminatedString(@enumFromInt(file.zir.extra[extra_index])) |
| 4325 | const doc_comment_index: Zir.NullTerminatedString = @enumFromInt(file.zir.extra[@intFromEnum(d.sub_index) + 7]); | ||
| 4326 | |||
| 4327 | // This is known to work because decl values are always block_inlines | ||
| 4328 | const value_pl_node = data[@intFromEnum(value_index)].pl_node; | ||
| 4329 | const decl_src = try self.srcLocInfo(file, value_pl_node.src_node, parent_src); | ||
| 4330 | |||
| 4331 | const doc_comment: ?[]const u8 = if (doc_comment_index != .empty) | ||
| 4332 | file.zir.nullTerminatedString(doc_comment_index) | ||
| 4333 | else | 4283 | else |
| 4334 | null; | 4284 | null; |
| 4335 | 4285 | ||
| ... | @@ -4346,11 +4296,12 @@ fn analyzeUsingnamespaceDecl( | ... | @@ -4346,11 +4296,12 @@ fn analyzeUsingnamespaceDecl( |
| 4346 | break :idx idx; | 4296 | break :idx idx; |
| 4347 | }; | 4297 | }; |
| 4348 | 4298 | ||
| 4349 | const walk_result = try self.walkInstruction( | 4299 | const walk_result = try self.walkInlineBody( |
| 4350 | file, | 4300 | file, |
| 4351 | scope, | 4301 | scope, |
| 4352 | decl_src, | 4302 | decl_src, |
| 4353 | value_index, | 4303 | decl_src, |
| 4304 | bodies.value_body, | ||
| 4354 | true, | 4305 | true, |
| 4355 | call_ctx, | 4306 | call_ctx, |
| 4356 | ); | 4307 | ); |
| ... | @@ -4365,7 +4316,7 @@ fn analyzeUsingnamespaceDecl( | ... | @@ -4365,7 +4316,7 @@ fn analyzeUsingnamespaceDecl( |
| 4365 | .parent_container = scope.enclosing_type, | 4316 | .parent_container = scope.enclosing_type, |
| 4366 | }); | 4317 | }); |
| 4367 | 4318 | ||
| 4368 | if (is_pub) { | 4319 | if (declaration.flags.is_pub) { |
| 4369 | try decl_indexes.append(self.arena, decl_slot_index); | 4320 | try decl_indexes.append(self.arena, decl_slot_index); |
| 4370 | } else { | 4321 | } else { |
| 4371 | try priv_decl_indexes.append(self.arena, decl_slot_index); | 4322 | try priv_decl_indexes.append(self.arena, decl_slot_index); |
| ... | @@ -4376,18 +4327,14 @@ fn analyzeDecltest( | ... | @@ -4376,18 +4327,14 @@ fn analyzeDecltest( |
| 4376 | self: *Autodoc, | 4327 | self: *Autodoc, |
| 4377 | file: *File, | 4328 | file: *File, |
| 4378 | scope: *Scope, | 4329 | scope: *Scope, |
| 4379 | parent_src: SrcLocInfo, | 4330 | decl_src: SrcLocInfo, |
| 4380 | d: Zir.DeclIterator.Item, | 4331 | declaration: Zir.Inst.Declaration, |
| 4332 | extra_index: u32, | ||
| 4381 | ) AutodocErrors!void { | 4333 | ) AutodocErrors!void { |
| 4382 | const data = file.zir.instructions.items(.data); | 4334 | std.debug.assert(declaration.flags.has_doc_comment); |
| 4383 | 4335 | const decl_name_index: Zir.NullTerminatedString = @enumFromInt(file.zir.extra[extra_index]); | |
| 4384 | const value_index = file.zir.extra[@intFromEnum(d.sub_index) + 6]; | ||
| 4385 | const decl_name_index: Zir.NullTerminatedString = @enumFromInt(file.zir.extra[@intFromEnum(d.sub_index) + 7]); | ||
| 4386 | |||
| 4387 | const value_pl_node = data[value_index].pl_node; | ||
| 4388 | const decl_src = try self.srcLocInfo(file, value_pl_node.src_node, parent_src); | ||
| 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 | const decl_name: ?[]const u8 = if (decl_name_index != .empty) | 4339 | const decl_name: ?[]const u8 = if (decl_name_index != .empty) |
| 4393 | file.zir.nullTerminatedString(decl_name_index) | 4340 | file.zir.nullTerminatedString(decl_name_index) |
| ... | @@ -5830,17 +5777,6 @@ fn walkRef( | ... | @@ -5830,17 +5777,6 @@ fn walkRef( |
| 5830 | } | 5777 | } |
| 5831 | } | 5778 | } |
| 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 | fn printWithContext( | 5780 | fn printWithContext( |
| 5845 | file: *File, | 5781 | file: *File, |
| 5846 | inst: Zir.Inst.Index, | 5782 | inst: Zir.Inst.Index, |
src/InternPool.zig-2| ... | @@ -6186,8 +6186,6 @@ fn finishFuncInstance( | ... | @@ -6186,8 +6186,6 @@ fn finishFuncInstance( |
| 6186 | .generation = generation, | 6186 | .generation = generation, |
| 6187 | .is_pub = fn_owner_decl.is_pub, | 6187 | .is_pub = fn_owner_decl.is_pub, |
| 6188 | .is_exported = fn_owner_decl.is_exported, | 6188 | .is_exported = fn_owner_decl.is_exported, |
| 6189 | .has_linksection_or_addrspace = fn_owner_decl.has_linksection_or_addrspace, | ||
| 6190 | .has_align = fn_owner_decl.has_align, | ||
| 6191 | .alive = true, | 6189 | .alive = true, |
| 6192 | .kind = .anon, | 6190 | .kind = .anon, |
| 6193 | }); | 6191 | }); |
src/Module.zig+216-260| ... | @@ -386,11 +386,9 @@ pub const Decl = struct { | ... | @@ -386,11 +386,9 @@ pub const Decl = struct { |
| 386 | /// do not need to be loaded into memory in order to compute debug line numbers. | 386 | /// do not need to be loaded into memory in order to compute debug line numbers. |
| 387 | /// This value is absolute. | 387 | /// This value is absolute. |
| 388 | src_line: u32, | 388 | src_line: u32, |
| 389 | /// Index to ZIR `extra` array to the entry in the parent's decl structure | 389 | /// Index of the ZIR `declaration` instruction from which this `Decl` was created. |
| 390 | /// (the part that says "for every decls_len"). The first item at this index is | 390 | /// For the root `Decl` of a `File` and legacy anonymous decls, this is `.none`. |
| 391 | /// the contents hash, followed by line, name, etc. | 391 | zir_decl_index: Zir.Inst.OptionalIndex, |
| 392 | /// For anonymous decls and also the root Decl for a File, this is `none`. | ||
| 393 | zir_decl_index: Zir.OptionalExtraIndex, | ||
| 394 | 392 | ||
| 395 | /// Represents the "shallow" analysis status. For example, for decls that are functions, | 393 | /// Represents the "shallow" analysis status. For example, for decls that are functions, |
| 396 | /// the function type is analyzed with this set to `in_progress`, however, the semantic | 394 | /// the function type is analyzed with this set to `in_progress`, however, the semantic |
| ... | @@ -442,10 +440,6 @@ pub const Decl = struct { | ... | @@ -442,10 +440,6 @@ pub const Decl = struct { |
| 442 | is_pub: bool, | 440 | is_pub: bool, |
| 443 | /// Whether the corresponding AST decl has a `export` keyword. | 441 | /// Whether the corresponding AST decl has a `export` keyword. |
| 444 | is_exported: bool, | 442 | is_exported: bool, |
| 445 | /// Whether the ZIR code provides an align instruction. | ||
| 446 | has_align: bool, | ||
| 447 | /// Whether the ZIR code provides a linksection and address space instruction. | ||
| 448 | has_linksection_or_addrspace: bool, | ||
| 449 | /// Flag used by garbage collection to mark and sweep. | 443 | /// Flag used by garbage collection to mark and sweep. |
| 450 | /// Decls which correspond to an AST node always have this field set to `true`. | 444 | /// Decls which correspond to an AST node always have this field set to `true`. |
| 451 | /// Anonymous Decls are initialized with this field set to `false` and then it | 445 | /// Anonymous Decls are initialized with this field set to `false` and then it |
| ... | @@ -471,81 +465,19 @@ pub const Decl = struct { | ... | @@ -471,81 +465,19 @@ pub const Decl = struct { |
| 471 | const Index = InternPool.DeclIndex; | 465 | const Index = InternPool.DeclIndex; |
| 472 | const OptionalIndex = InternPool.OptionalDeclIndex; | 466 | const OptionalIndex = InternPool.OptionalDeclIndex; |
| 473 | 467 | ||
| 474 | pub const DepsTable = std.AutoArrayHashMapUnmanaged(Decl.Index, DepType); | 468 | /// Asserts that `zir_decl_index` is not `.none`. |
| 475 | 469 | fn getDeclaration(decl: Decl, zir: Zir) Zir.Inst.Declaration { | |
| 476 | /// Later types take priority; e.g. if a dependent decl has both `normal` | 470 | const zir_index = decl.zir_decl_index.unwrap().?; |
| 477 | /// and `function_body` dependencies on another decl, it will be marked as | 471 | const pl_node = zir.instructions.items(.data)[@intFromEnum(zir_index)].pl_node; |
| 478 | /// having a `function_body` dependency. | 472 | return zir.extraData(Zir.Inst.Declaration, pl_node.payload_index).data; |
| 479 | pub const DepType = enum { | ||
| 480 | /// The dependent references or uses the dependency's value, so must be | ||
| 481 | /// updated whenever it is changed. However, if the dependency is a | ||
| 482 | /// function and its type is unchanged, the dependent does not need to | ||
| 483 | /// be updated. | ||
| 484 | normal, | ||
| 485 | /// The dependent performs an inline or comptime call to the dependency, | ||
| 486 | /// or is a generic instantiation of it. It must therefore be updated | ||
| 487 | /// whenever the dependency is updated, even if the function type | ||
| 488 | /// remained the same. | ||
| 489 | function_body, | ||
| 490 | }; | ||
| 491 | |||
| 492 | /// This name is relative to the containing namespace of the decl. | ||
| 493 | /// The memory is owned by the containing File ZIR. | ||
| 494 | pub fn getName(decl: Decl, mod: *Module) ?[:0]const u8 { | ||
| 495 | const zir = decl.getFileScope(mod).zir; | ||
| 496 | return decl.getNameZir(zir); | ||
| 497 | } | 473 | } |
| 498 | 474 | ||
| 499 | pub fn getNameZir(decl: Decl, zir: Zir) ?[:0]const u8 { | 475 | pub fn zirBodies(decl: Decl, zcu: *Zcu) Zir.Inst.Declaration.Bodies { |
| 500 | assert(decl.zir_decl_index != .none); | 476 | const zir = decl.getFileScope(zcu).zir; |
| 501 | const name_index = zir.extra[@intFromEnum(decl.zir_decl_index) + 5]; | 477 | const zir_index = decl.zir_decl_index.unwrap().?; |
| 502 | if (name_index <= 1) return null; | 478 | const pl_node = zir.instructions.items(.data)[@intFromEnum(zir_index)].pl_node; |
| 503 | return zir.nullTerminatedString(name_index); | 479 | const extra = zir.extraData(Zir.Inst.Declaration, pl_node.payload_index); |
| 504 | } | 480 | return extra.data.getBodies(@intCast(extra.end), zir); |
| 505 | |||
| 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; | ||
| 549 | } | 481 | } |
| 550 | 482 | ||
| 551 | pub fn relativeToNodeIndex(decl: Decl, offset: i32) Ast.Node.Index { | 483 | pub fn relativeToNodeIndex(decl: Decl, offset: i32) Ast.Node.Index { |
| ... | @@ -3015,16 +2947,12 @@ fn updateZirRefs(mod: *Module, file: *File, old_zir: Zir) !void { | ... | @@ -3015,16 +2947,12 @@ fn updateZirRefs(mod: *Module, file: *File, old_zir: Zir) !void { |
| 3015 | // The root decl will be null if the previous ZIR had AST errors. | 2947 | // The root decl will be null if the previous ZIR had AST errors. |
| 3016 | const root_decl = file.root_decl.unwrap() orelse return; | 2948 | const root_decl = file.root_decl.unwrap() orelse return; |
| 3017 | 2949 | ||
| 3018 | // Maps from old ZIR to new ZIR, struct_decl, enum_decl, etc. Any instruction which | 2950 | // Maps from old ZIR to new ZIR, declaration, struct_decl, enum_decl, etc. Any instruction which |
| 3019 | // creates a namespace, gets mapped from old to new here. | 2951 | // creates a namespace, and any `declaration` instruction, gets mapped from old to new here. |
| 3020 | var inst_map: std.AutoHashMapUnmanaged(Zir.Inst.Index, Zir.Inst.Index) = .{}; | 2952 | var inst_map: std.AutoHashMapUnmanaged(Zir.Inst.Index, Zir.Inst.Index) = .{}; |
| 3021 | defer inst_map.deinit(gpa); | 2953 | 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 | 2954 | ||
| 3027 | try mapOldZirToNew(gpa, old_zir, new_zir, &inst_map, &extra_map); | 2955 | try mapOldZirToNew(gpa, old_zir, new_zir, &inst_map); |
| 3028 | 2956 | ||
| 3029 | // Walk the Decl graph, updating ZIR indexes, strings, and populating | 2957 | // Walk the Decl graph, updating ZIR indexes, strings, and populating |
| 3030 | // the deleted and outdated lists. | 2958 | // the deleted and outdated lists. |
| ... | @@ -3050,7 +2978,7 @@ fn updateZirRefs(mod: *Module, file: *File, old_zir: Zir) !void { | ... | @@ -3050,7 +2978,7 @@ fn updateZirRefs(mod: *Module, file: *File, old_zir: Zir) !void { |
| 3050 | // Anonymous decls should not be marked outdated. They will be re-generated | 2978 | // Anonymous decls should not be marked outdated. They will be re-generated |
| 3051 | // if their owner decl is marked outdated. | 2979 | // if their owner decl is marked outdated. |
| 3052 | if (decl.zir_decl_index.unwrap()) |old_zir_decl_index| { | 2980 | if (decl.zir_decl_index.unwrap()) |old_zir_decl_index| { |
| 3053 | const new_zir_decl_index = extra_map.get(old_zir_decl_index) orelse { | 2981 | const new_zir_decl_index = inst_map.get(old_zir_decl_index) orelse { |
| 3054 | try file.deleted_decls.append(gpa, decl_index); | 2982 | try file.deleted_decls.append(gpa, decl_index); |
| 3055 | continue; | 2983 | continue; |
| 3056 | }; | 2984 | }; |
| ... | @@ -3098,9 +3026,9 @@ pub fn mapOldZirToNew( | ... | @@ -3098,9 +3026,9 @@ pub fn mapOldZirToNew( |
| 3098 | old_zir: Zir, | 3026 | old_zir: Zir, |
| 3099 | new_zir: Zir, | 3027 | new_zir: Zir, |
| 3100 | inst_map: *std.AutoHashMapUnmanaged(Zir.Inst.Index, Zir.Inst.Index), | 3028 | inst_map: *std.AutoHashMapUnmanaged(Zir.Inst.Index, Zir.Inst.Index), |
| 3101 | extra_map: *std.AutoHashMapUnmanaged(Zir.ExtraIndex, Zir.ExtraIndex), | ||
| 3102 | ) Allocator.Error!void { | 3029 | ) Allocator.Error!void { |
| 3103 | // Contain ZIR indexes of declaration instructions. | 3030 | // Contain ZIR indexes of namespace declaration instructions, e.g. struct_decl, union_decl, etc. |
| 3031 | // Not `declaration`, as this does not create a namespace. | ||
| 3104 | const MatchedZirDecl = struct { | 3032 | const MatchedZirDecl = struct { |
| 3105 | old_inst: Zir.Inst.Index, | 3033 | old_inst: Zir.Inst.Index, |
| 3106 | new_inst: Zir.Inst.Index, | 3034 | new_inst: Zir.Inst.Index, |
| ... | @@ -3108,47 +3036,113 @@ pub fn mapOldZirToNew( | ... | @@ -3108,47 +3036,113 @@ pub fn mapOldZirToNew( |
| 3108 | var match_stack: ArrayListUnmanaged(MatchedZirDecl) = .{}; | 3036 | var match_stack: ArrayListUnmanaged(MatchedZirDecl) = .{}; |
| 3109 | defer match_stack.deinit(gpa); | 3037 | defer match_stack.deinit(gpa); |
| 3110 | 3038 | ||
| 3111 | // Main struct inst is always the same | 3039 | // Main struct inst is always matched |
| 3112 | try match_stack.append(gpa, .{ | 3040 | try match_stack.append(gpa, .{ |
| 3113 | .old_inst = .main_struct_inst, | 3041 | .old_inst = .main_struct_inst, |
| 3114 | .new_inst = .main_struct_inst, | 3042 | .new_inst = .main_struct_inst, |
| 3115 | }); | 3043 | }); |
| 3116 | 3044 | ||
| 3045 | // Used as temporary buffers for namespace declaration instructions | ||
| 3117 | var old_decls = std.ArrayList(Zir.Inst.Index).init(gpa); | 3046 | var old_decls = std.ArrayList(Zir.Inst.Index).init(gpa); |
| 3118 | defer old_decls.deinit(); | 3047 | defer old_decls.deinit(); |
| 3119 | var new_decls = std.ArrayList(Zir.Inst.Index).init(gpa); | 3048 | var new_decls = std.ArrayList(Zir.Inst.Index).init(gpa); |
| 3120 | defer new_decls.deinit(); | 3049 | defer new_decls.deinit(); |
| 3121 | 3050 | ||
| 3122 | while (match_stack.popOrNull()) |match_item| { | 3051 | while (match_stack.popOrNull()) |match_item| { |
| 3052 | // Match the namespace declaration itself | ||
| 3123 | try inst_map.put(gpa, match_item.old_inst, match_item.new_inst); | 3053 | try inst_map.put(gpa, match_item.old_inst, match_item.new_inst); |
| 3124 | 3054 | ||
| 3125 | // Maps name to extra index of decl sub item. | 3055 | // Maps decl name to `declaration` instruction. |
| 3126 | var decl_map: std.StringHashMapUnmanaged(Zir.ExtraIndex) = .{}; | 3056 | var named_decls: std.StringHashMapUnmanaged(Zir.Inst.Index) = .{}; |
| 3127 | defer decl_map.deinit(gpa); | 3057 | defer named_decls.deinit(gpa); |
| 3058 | // Maps test name to `declaration` instruction. | ||
| 3059 | var named_tests: std.StringHashMapUnmanaged(Zir.Inst.Index) = .{}; | ||
| 3060 | defer named_tests.deinit(gpa); | ||
| 3061 | // All unnamed tests, in order, for a best-effort match. | ||
| 3062 | var unnamed_tests: std.ArrayListUnmanaged(Zir.Inst.Index) = .{}; | ||
| 3063 | defer unnamed_tests.deinit(gpa); | ||
| 3064 | // All comptime declarations, in order, for a best-effort match. | ||
| 3065 | var comptime_decls: std.ArrayListUnmanaged(Zir.Inst.Index) = .{}; | ||
| 3066 | defer comptime_decls.deinit(gpa); | ||
| 3067 | // All usingnamespace declarations, in order, for a best-effort match. | ||
| 3068 | var usingnamespace_decls: std.ArrayListUnmanaged(Zir.Inst.Index) = .{}; | ||
| 3069 | defer usingnamespace_decls.deinit(gpa); | ||
| 3128 | 3070 | ||
| 3129 | { | 3071 | { |
| 3130 | var old_decl_it = old_zir.declIterator(match_item.old_inst); | 3072 | var old_decl_it = old_zir.declIterator(match_item.old_inst); |
| 3131 | while (old_decl_it.next()) |old_decl| { | 3073 | while (old_decl_it.next()) |old_decl_inst| { |
| 3132 | try decl_map.put(gpa, old_decl.name, old_decl.sub_index); | 3074 | const old_decl, _ = old_zir.getDeclaration(old_decl_inst); |
| 3075 | switch (old_decl.name) { | ||
| 3076 | .@"comptime" => try comptime_decls.append(gpa, old_decl_inst), | ||
| 3077 | .@"usingnamespace" => try usingnamespace_decls.append(gpa, old_decl_inst), | ||
| 3078 | .unnamed_test, .decltest => try unnamed_tests.append(gpa, old_decl_inst), | ||
| 3079 | _ => { | ||
| 3080 | const name_nts = old_decl.name.toString(old_zir).?; | ||
| 3081 | const name = old_zir.nullTerminatedString(name_nts); | ||
| 3082 | if (old_decl.name.isNamedTest(old_zir)) { | ||
| 3083 | try named_tests.put(gpa, name, old_decl_inst); | ||
| 3084 | } else { | ||
| 3085 | try named_decls.put(gpa, name, old_decl_inst); | ||
| 3086 | } | ||
| 3087 | }, | ||
| 3088 | } | ||
| 3133 | } | 3089 | } |
| 3134 | } | 3090 | } |
| 3135 | 3091 | ||
| 3092 | var unnamed_test_idx: u32 = 0; | ||
| 3093 | var comptime_decl_idx: u32 = 0; | ||
| 3094 | var usingnamespace_decl_idx: u32 = 0; | ||
| 3095 | |||
| 3136 | var new_decl_it = new_zir.declIterator(match_item.new_inst); | 3096 | var new_decl_it = new_zir.declIterator(match_item.new_inst); |
| 3137 | while (new_decl_it.next()) |new_decl| { | 3097 | while (new_decl_it.next()) |new_decl_inst| { |
| 3138 | const old_extra_index = decl_map.get(new_decl.name) orelse continue; | 3098 | const new_decl, _ = new_zir.getDeclaration(new_decl_inst); |
| 3139 | const new_extra_index = new_decl.sub_index; | 3099 | // Attempt to match this to a declaration in the old ZIR: |
| 3140 | try extra_map.put(gpa, old_extra_index, new_extra_index); | 3100 | // * For named declarations (`const`/`var`/`fn`), we match based on name. |
| 3141 | 3101 | // * For named tests (`test "foo"`), we also match based on name. | |
| 3142 | try old_zir.findDecls(&old_decls, old_extra_index); | 3102 | // * For unnamed tests and decltests, we match based on order. |
| 3143 | try new_zir.findDecls(&new_decls, new_extra_index); | 3103 | // * For comptime blocks, we match based on order. |
| 3144 | var i: usize = 0; | 3104 | // * For usingnamespace decls, we match based on order. |
| 3145 | while (true) : (i += 1) { | 3105 | // If we cannot match this declaration, we can't match anything nested inside of it either, so we just `continue`. |
| 3146 | if (i >= old_decls.items.len) break; | 3106 | const old_decl_inst = switch (new_decl.name) { |
| 3147 | if (i >= new_decls.items.len) break; | 3107 | .@"comptime" => inst: { |
| 3148 | try match_stack.append(gpa, .{ | 3108 | if (comptime_decl_idx == comptime_decls.items.len) continue; |
| 3149 | .old_inst = old_decls.items[i], | 3109 | defer comptime_decl_idx += 1; |
| 3150 | .new_inst = new_decls.items[i], | 3110 | break :inst comptime_decls.items[comptime_decl_idx]; |
| 3151 | }); | 3111 | }, |
| 3112 | .@"usingnamespace" => inst: { | ||
| 3113 | if (usingnamespace_decl_idx == usingnamespace_decls.items.len) continue; | ||
| 3114 | defer usingnamespace_decl_idx += 1; | ||
| 3115 | break :inst usingnamespace_decls.items[usingnamespace_decl_idx]; | ||
| 3116 | }, | ||
| 3117 | .unnamed_test, .decltest => inst: { | ||
| 3118 | if (unnamed_test_idx == unnamed_tests.items.len) continue; | ||
| 3119 | defer unnamed_test_idx += 1; | ||
| 3120 | break :inst unnamed_tests.items[unnamed_test_idx]; | ||
| 3121 | }, | ||
| 3122 | _ => inst: { | ||
| 3123 | const name_nts = new_decl.name.toString(old_zir).?; | ||
| 3124 | const name = new_zir.nullTerminatedString(name_nts); | ||
| 3125 | if (new_decl.name.isNamedTest(new_zir)) { | ||
| 3126 | break :inst named_tests.get(name) orelse continue; | ||
| 3127 | } else { | ||
| 3128 | break :inst named_decls.get(name) orelse continue; | ||
| 3129 | } | ||
| 3130 | }, | ||
| 3131 | }; | ||
| 3132 | |||
| 3133 | // Match the `declaration` instruction | ||
| 3134 | try inst_map.put(gpa, old_decl_inst, new_decl_inst); | ||
| 3135 | |||
| 3136 | // Find namespace declarations within this declaration | ||
| 3137 | try old_zir.findDecls(&old_decls, old_decl_inst); | ||
| 3138 | try new_zir.findDecls(&new_decls, new_decl_inst); | ||
| 3139 | |||
| 3140 | // We don't have any smart way of matching up these namespace declarations, so we always | ||
| 3141 | // correlate them based on source order. | ||
| 3142 | const n = @min(old_decls.items.len, new_decls.items.len); | ||
| 3143 | try match_stack.ensureUnusedCapacity(gpa, n); | ||
| 3144 | for (old_decls.items[0..n], new_decls.items[0..n]) |old_inst, new_inst| { | ||
| 3145 | match_stack.appendAssumeCapacity(.{ .old_inst = old_inst, .new_inst = new_inst }); | ||
| 3152 | } | 3146 | } |
| 3153 | } | 3147 | } |
| 3154 | } | 3148 | } |
| ... | @@ -3457,8 +3451,6 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void { | ... | @@ -3457,8 +3451,6 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void { |
| 3457 | new_decl.src_line = 0; | 3451 | new_decl.src_line = 0; |
| 3458 | new_decl.is_pub = true; | 3452 | new_decl.is_pub = true; |
| 3459 | new_decl.is_exported = false; | 3453 | new_decl.is_exported = false; |
| 3460 | new_decl.has_align = false; | ||
| 3461 | new_decl.has_linksection_or_addrspace = false; | ||
| 3462 | new_decl.ty = Type.type; | 3454 | new_decl.ty = Type.type; |
| 3463 | new_decl.alignment = .none; | 3455 | new_decl.alignment = .none; |
| 3464 | new_decl.@"linksection" = .none; | 3456 | new_decl.@"linksection" = .none; |
| ... | @@ -3561,7 +3553,6 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { | ... | @@ -3561,7 +3553,6 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { |
| 3561 | 3553 | ||
| 3562 | const gpa = mod.gpa; | 3554 | const gpa = mod.gpa; |
| 3563 | const zir = decl.getFileScope(mod).zir; | 3555 | const zir = decl.getFileScope(mod).zir; |
| 3564 | const zir_datas = zir.instructions.items(.data); | ||
| 3565 | 3556 | ||
| 3566 | const builtin_type_target_index: InternPool.Index = blk: { | 3557 | const builtin_type_target_index: InternPool.Index = blk: { |
| 3567 | const std_mod = mod.std_mod; | 3558 | const std_mod = mod.std_mod; |
| ... | @@ -3639,11 +3630,9 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { | ... | @@ -3639,11 +3630,9 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { |
| 3639 | }; | 3630 | }; |
| 3640 | defer block_scope.instructions.deinit(gpa); | 3631 | defer block_scope.instructions.deinit(gpa); |
| 3641 | 3632 | ||
| 3642 | const zir_block_index = decl.zirBlockIndex(mod); | 3633 | const decl_bodies = decl.zirBodies(mod); |
| 3643 | const inst_data = zir_datas[@intFromEnum(zir_block_index)].pl_node; | 3634 | |
| 3644 | const extra = zir.extraData(Zir.Inst.Block, inst_data.payload_index); | 3635 | const result_ref = (try sema.analyzeBodyBreak(&block_scope, decl_bodies.value_body)).?.operand; |
| 3645 | const body = zir.extra[extra.end..][0..extra.data.body_len]; | ||
| 3646 | const result_ref = (try sema.analyzeBodyBreak(&block_scope, @ptrCast(body))).?.operand; | ||
| 3647 | // We'll do some other bits with the Sema. Clear the type target index just | 3636 | // We'll do some other bits with the Sema. Clear the type target index just |
| 3648 | // in case they analyze any type. | 3637 | // in case they analyze any type. |
| 3649 | sema.builtin_type_target_index = .none; | 3638 | sema.builtin_type_target_index = .none; |
| ... | @@ -3760,13 +3749,13 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { | ... | @@ -3760,13 +3749,13 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { |
| 3760 | decl.ty = decl_tv.ty; | 3749 | decl.ty = decl_tv.ty; |
| 3761 | decl.val = Value.fromInterned((try decl_tv.val.intern(decl_tv.ty, mod))); | 3750 | decl.val = Value.fromInterned((try decl_tv.val.intern(decl_tv.ty, mod))); |
| 3762 | decl.alignment = blk: { | 3751 | decl.alignment = blk: { |
| 3763 | const align_ref = decl.zirAlignRef(mod); | 3752 | const align_body = decl_bodies.align_body orelse break :blk .none; |
| 3764 | if (align_ref == .none) break :blk .none; | 3753 | const align_ref = (try sema.analyzeBodyBreak(&block_scope, align_body)).?.operand; |
| 3765 | break :blk try sema.resolveAlign(&block_scope, align_src, align_ref); | 3754 | break :blk try sema.resolveAlign(&block_scope, align_src, align_ref); |
| 3766 | }; | 3755 | }; |
| 3767 | decl.@"linksection" = blk: { | 3756 | decl.@"linksection" = blk: { |
| 3768 | const linksection_ref = decl.zirLinksectionRef(mod); | 3757 | const linksection_body = decl_bodies.linksection_body orelse break :blk .none; |
| 3769 | if (linksection_ref == .none) break :blk .none; | 3758 | const linksection_ref = (try sema.analyzeBodyBreak(&block_scope, linksection_body)).?.operand; |
| 3770 | const bytes = try sema.resolveConstString(&block_scope, section_src, linksection_ref, .{ | 3759 | const bytes = try sema.resolveConstString(&block_scope, section_src, linksection_ref, .{ |
| 3771 | .needed_comptime_reason = "linksection must be comptime-known", | 3760 | .needed_comptime_reason = "linksection must be comptime-known", |
| 3772 | }); | 3761 | }); |
| ... | @@ -3786,15 +3775,15 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { | ... | @@ -3786,15 +3775,15 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { |
| 3786 | }; | 3775 | }; |
| 3787 | 3776 | ||
| 3788 | const target = sema.mod.getTarget(); | 3777 | const target = sema.mod.getTarget(); |
| 3789 | break :blk switch (decl.zirAddrspaceRef(mod)) { | 3778 | |
| 3790 | .none => switch (addrspace_ctx) { | 3779 | const addrspace_body = decl_bodies.addrspace_body orelse break :blk switch (addrspace_ctx) { |
| 3791 | .function => target_util.defaultAddressSpace(target, .function), | 3780 | .function => target_util.defaultAddressSpace(target, .function), |
| 3792 | .variable => target_util.defaultAddressSpace(target, .global_mutable), | 3781 | .variable => target_util.defaultAddressSpace(target, .global_mutable), |
| 3793 | .constant => target_util.defaultAddressSpace(target, .global_constant), | 3782 | .constant => target_util.defaultAddressSpace(target, .global_constant), |
| 3794 | else => unreachable, | 3783 | else => unreachable, |
| 3795 | }, | ||
| 3796 | else => |addrspace_ref| try sema.analyzeAddressSpace(&block_scope, address_space_src, addrspace_ref, addrspace_ctx), | ||
| 3797 | }; | 3784 | }; |
| 3785 | const addrspace_ref = (try sema.analyzeBodyBreak(&block_scope, addrspace_body)).?.operand; | ||
| 3786 | break :blk try sema.analyzeAddressSpace(&block_scope, address_space_src, addrspace_ref, addrspace_ctx); | ||
| 3798 | }; | 3787 | }; |
| 3799 | decl.has_tv = true; | 3788 | decl.has_tv = true; |
| 3800 | decl.analysis = .complete; | 3789 | decl.analysis = .complete; |
| ... | @@ -4133,52 +4122,32 @@ fn newEmbedFile( | ... | @@ -4133,52 +4122,32 @@ fn newEmbedFile( |
| 4133 | } | 4122 | } |
| 4134 | 4123 | ||
| 4135 | pub fn scanNamespace( | 4124 | pub fn scanNamespace( |
| 4136 | mod: *Module, | 4125 | zcu: *Zcu, |
| 4137 | namespace_index: Namespace.Index, | 4126 | namespace_index: Namespace.Index, |
| 4138 | extra_start: usize, | 4127 | decls: []const Zir.Inst.Index, |
| 4139 | decls_len: u32, | ||
| 4140 | parent_decl: *Decl, | 4128 | parent_decl: *Decl, |
| 4141 | ) Allocator.Error!usize { | 4129 | ) Allocator.Error!void { |
| 4142 | const tracy = trace(@src()); | 4130 | const tracy = trace(@src()); |
| 4143 | defer tracy.end(); | 4131 | defer tracy.end(); |
| 4144 | 4132 | ||
| 4145 | const gpa = mod.gpa; | 4133 | const gpa = zcu.gpa; |
| 4146 | const namespace = mod.namespacePtr(namespace_index); | 4134 | const namespace = zcu.namespacePtr(namespace_index); |
| 4147 | const zir = namespace.file_scope.zir; | ||
| 4148 | 4135 | ||
| 4149 | try mod.comp.work_queue.ensureUnusedCapacity(decls_len); | 4136 | try zcu.comp.work_queue.ensureUnusedCapacity(decls.len); |
| 4150 | try namespace.decls.ensureTotalCapacity(gpa, decls_len); | 4137 | try namespace.decls.ensureTotalCapacity(gpa, decls.len); |
| 4151 | 4138 | ||
| 4152 | const bit_bags_count = std.math.divCeil(usize, decls_len, 8) catch unreachable; | ||
| 4153 | var extra_index = extra_start + bit_bags_count; | ||
| 4154 | var bit_bag_index: usize = extra_start; | ||
| 4155 | var cur_bit_bag: u32 = undefined; | ||
| 4156 | var decl_i: u32 = 0; | ||
| 4157 | var scan_decl_iter: ScanDeclIter = .{ | 4139 | var scan_decl_iter: ScanDeclIter = .{ |
| 4158 | .module = mod, | 4140 | .zcu = zcu, |
| 4159 | .namespace_index = namespace_index, | 4141 | .namespace_index = namespace_index, |
| 4160 | .parent_decl = parent_decl, | 4142 | .parent_decl = parent_decl, |
| 4161 | }; | 4143 | }; |
| 4162 | while (decl_i < decls_len) : (decl_i += 1) { | 4144 | for (decls) |decl_inst| { |
| 4163 | if (decl_i % 8 == 0) { | 4145 | try scanDecl(&scan_decl_iter, decl_inst); |
| 4164 | cur_bit_bag = zir.extra[bit_bag_index]; | ||
| 4165 | bit_bag_index += 1; | ||
| 4166 | } | ||
| 4167 | const flags = @as(u4, @truncate(cur_bit_bag)); | ||
| 4168 | cur_bit_bag >>= 4; | ||
| 4169 | |||
| 4170 | const decl_sub_index = extra_index; | ||
| 4171 | extra_index += 8; // src_hash(4) + line(1) + name(1) + value(1) + doc_comment(1) | ||
| 4172 | extra_index += @as(u1, @truncate(flags >> 2)); // Align | ||
| 4173 | extra_index += @as(u2, @as(u1, @truncate(flags >> 3))) * 2; // Link section or address space, consists of 2 Refs | ||
| 4174 | |||
| 4175 | try scanDecl(&scan_decl_iter, decl_sub_index, flags); | ||
| 4176 | } | 4146 | } |
| 4177 | return extra_index; | ||
| 4178 | } | 4147 | } |
| 4179 | 4148 | ||
| 4180 | const ScanDeclIter = struct { | 4149 | const ScanDeclIter = struct { |
| 4181 | module: *Module, | 4150 | zcu: *Zcu, |
| 4182 | namespace_index: Namespace.Index, | 4151 | namespace_index: Namespace.Index, |
| 4183 | parent_decl: *Decl, | 4152 | parent_decl: *Decl, |
| 4184 | usingnamespace_index: usize = 0, | 4153 | usingnamespace_index: usize = 0, |
| ... | @@ -4186,119 +4155,112 @@ const ScanDeclIter = struct { | ... | @@ -4186,119 +4155,112 @@ const ScanDeclIter = struct { |
| 4186 | unnamed_test_index: usize = 0, | 4155 | unnamed_test_index: usize = 0, |
| 4187 | }; | 4156 | }; |
| 4188 | 4157 | ||
| 4189 | fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Error!void { | 4158 | fn scanDecl(iter: *ScanDeclIter, decl_inst: Zir.Inst.Index) Allocator.Error!void { |
| 4190 | const tracy = trace(@src()); | 4159 | const tracy = trace(@src()); |
| 4191 | defer tracy.end(); | 4160 | defer tracy.end(); |
| 4192 | 4161 | ||
| 4193 | const mod = iter.module; | 4162 | const zcu = iter.zcu; |
| 4194 | const namespace_index = iter.namespace_index; | 4163 | const namespace_index = iter.namespace_index; |
| 4195 | const namespace = mod.namespacePtr(namespace_index); | 4164 | const namespace = zcu.namespacePtr(namespace_index); |
| 4196 | const gpa = mod.gpa; | 4165 | const gpa = zcu.gpa; |
| 4197 | const zir = namespace.file_scope.zir; | 4166 | const zir = namespace.file_scope.zir; |
| 4198 | const ip = &mod.intern_pool; | 4167 | const ip = &zcu.intern_pool; |
| 4168 | |||
| 4169 | const pl_node = zir.instructions.items(.data)[@intFromEnum(decl_inst)].pl_node; | ||
| 4170 | const extra = zir.extraData(Zir.Inst.Declaration, pl_node.payload_index); | ||
| 4171 | const declaration = extra.data; | ||
| 4199 | 4172 | ||
| 4200 | // zig fmt: off | 4173 | const line = iter.parent_decl.src_line + declaration.line_offset; |
| 4201 | const is_pub = (flags & 0b0001) != 0; | 4174 | const decl_node = iter.parent_decl.relativeToNodeIndex(pl_node.src_node); |
| 4202 | const export_bit = (flags & 0b0010) != 0; | ||
| 4203 | const has_align = (flags & 0b0100) != 0; | ||
| 4204 | const has_linksection_or_addrspace = (flags & 0b1000) != 0; | ||
| 4205 | // zig fmt: on | ||
| 4206 | |||
| 4207 | const line_off = zir.extra[decl_sub_index + 4]; | ||
| 4208 | const line = iter.parent_decl.relativeToLine(line_off); | ||
| 4209 | const decl_name_index: Zir.NullTerminatedString = @enumFromInt(zir.extra[decl_sub_index + 5]); | ||
| 4210 | const decl_doccomment_index = zir.extra[decl_sub_index + 7]; | ||
| 4211 | const decl_zir_index = zir.extra[decl_sub_index + 6]; | ||
| 4212 | const decl_block_inst_data = zir.instructions.items(.data)[decl_zir_index].pl_node; | ||
| 4213 | const decl_node = iter.parent_decl.relativeToNodeIndex(decl_block_inst_data.src_node); | ||
| 4214 | 4175 | ||
| 4215 | // Every Decl needs a name. | 4176 | // Every Decl needs a name. |
| 4216 | var is_named_test = false; | 4177 | const decl_name: InternPool.NullTerminatedString, const kind: Decl.Kind, const is_named_test: bool = switch (declaration.name) { |
| 4217 | var kind: Decl.Kind = .named; | 4178 | .@"comptime" => info: { |
| 4218 | const decl_name: InternPool.NullTerminatedString = switch (decl_name_index) { | 4179 | const i = iter.comptime_index; |
| 4219 | .empty => name: { | 4180 | iter.comptime_index += 1; |
| 4220 | if (export_bit) { | 4181 | break :info .{ |
| 4221 | const i = iter.usingnamespace_index; | 4182 | try ip.getOrPutStringFmt(gpa, "comptime_{d}", .{i}), |
| 4222 | iter.usingnamespace_index += 1; | 4183 | .@"comptime", |
| 4223 | kind = .@"usingnamespace"; | 4184 | false, |
| 4224 | break :name try ip.getOrPutStringFmt(gpa, "usingnamespace_{d}", .{i}); | 4185 | }; |
| 4225 | } else { | 4186 | }, |
| 4226 | const i = iter.comptime_index; | 4187 | .@"usingnamespace" => info: { |
| 4227 | iter.comptime_index += 1; | 4188 | const i = iter.usingnamespace_index; |
| 4228 | kind = .@"comptime"; | 4189 | iter.usingnamespace_index += 1; |
| 4229 | break :name try ip.getOrPutStringFmt(gpa, "comptime_{d}", .{i}); | 4190 | break :info .{ |
| 4230 | } | 4191 | try ip.getOrPutStringFmt(gpa, "usingnamespace_{d}", .{i}), |
| 4192 | .@"usingnamespace", | ||
| 4193 | false, | ||
| 4194 | }; | ||
| 4231 | }, | 4195 | }, |
| 4232 | .unnamed_test_decl => name: { | 4196 | .unnamed_test => info: { |
| 4233 | const i = iter.unnamed_test_index; | 4197 | const i = iter.unnamed_test_index; |
| 4234 | iter.unnamed_test_index += 1; | 4198 | iter.unnamed_test_index += 1; |
| 4235 | kind = .@"test"; | 4199 | break :info .{ |
| 4236 | break :name try ip.getOrPutStringFmt(gpa, "test_{d}", .{i}); | 4200 | try ip.getOrPutStringFmt(gpa, "test_{d}", .{i}), |
| 4201 | .@"test", | ||
| 4202 | false, | ||
| 4203 | }; | ||
| 4237 | }, | 4204 | }, |
| 4238 | .decltest => name: { | 4205 | .decltest => info: { |
| 4239 | is_named_test = true; | 4206 | assert(declaration.flags.has_doc_comment); |
| 4240 | const test_name = zir.nullTerminatedString(@enumFromInt(decl_doccomment_index)); | 4207 | const name = zir.nullTerminatedString(@enumFromInt(zir.extra[extra.end])); |
| 4241 | kind = .@"test"; | 4208 | break :info .{ |
| 4242 | break :name try ip.getOrPutStringFmt(gpa, "decltest.{s}", .{test_name}); | 4209 | try ip.getOrPutStringFmt(gpa, "decltest.{s}", .{name}), |
| 4210 | .@"test", | ||
| 4211 | true, | ||
| 4212 | }; | ||
| 4243 | }, | 4213 | }, |
| 4244 | _ => name: { | 4214 | _ => if (declaration.name.isNamedTest(zir)) .{ |
| 4245 | const raw_name = zir.nullTerminatedString(decl_name_index); | 4215 | try ip.getOrPutStringFmt(gpa, "test.{s}", .{zir.nullTerminatedString(declaration.name.toString(zir).?)}), |
| 4246 | if (raw_name.len == 0) { | 4216 | .@"test", |
| 4247 | is_named_test = true; | 4217 | true, |
| 4248 | const test_name = zir.nullTerminatedString(@enumFromInt(@intFromEnum(decl_name_index) + 1)); | 4218 | } else .{ |
| 4249 | kind = .@"test"; | 4219 | try ip.getOrPutString(gpa, zir.nullTerminatedString(declaration.name.toString(zir).?)), |
| 4250 | break :name try ip.getOrPutStringFmt(gpa, "test.{s}", .{test_name}); | 4220 | .named, |
| 4251 | } else { | 4221 | false, |
| 4252 | break :name try ip.getOrPutString(gpa, raw_name); | ||
| 4253 | } | ||
| 4254 | }, | 4222 | }, |
| 4255 | }; | 4223 | }; |
| 4256 | 4224 | ||
| 4257 | const is_exported = export_bit and decl_name_index != .empty; | ||
| 4258 | if (kind == .@"usingnamespace") try namespace.usingnamespace_set.ensureUnusedCapacity(gpa, 1); | 4225 | if (kind == .@"usingnamespace") try namespace.usingnamespace_set.ensureUnusedCapacity(gpa, 1); |
| 4259 | 4226 | ||
| 4260 | // We create a Decl for it regardless of analysis status. | 4227 | // We create a Decl for it regardless of analysis status. |
| 4261 | const gop = try namespace.decls.getOrPutContextAdapted( | 4228 | const gop = try namespace.decls.getOrPutContextAdapted( |
| 4262 | gpa, | 4229 | gpa, |
| 4263 | decl_name, | 4230 | decl_name, |
| 4264 | DeclAdapter{ .mod = mod }, | 4231 | DeclAdapter{ .mod = zcu }, |
| 4265 | Namespace.DeclContext{ .module = mod }, | 4232 | Namespace.DeclContext{ .module = zcu }, |
| 4266 | ); | 4233 | ); |
| 4267 | const comp = mod.comp; | 4234 | const comp = zcu.comp; |
| 4268 | if (!gop.found_existing) { | 4235 | if (!gop.found_existing) { |
| 4269 | const new_decl_index = try mod.allocateNewDecl(namespace_index, decl_node, iter.parent_decl.src_scope); | 4236 | const new_decl_index = try zcu.allocateNewDecl(namespace_index, decl_node, iter.parent_decl.src_scope); |
| 4270 | const new_decl = mod.declPtr(new_decl_index); | 4237 | const new_decl = zcu.declPtr(new_decl_index); |
| 4271 | new_decl.kind = kind; | 4238 | new_decl.kind = kind; |
| 4272 | new_decl.name = decl_name; | 4239 | new_decl.name = decl_name; |
| 4273 | if (kind == .@"usingnamespace") { | 4240 | if (kind == .@"usingnamespace") { |
| 4274 | namespace.usingnamespace_set.putAssumeCapacity(new_decl_index, is_pub); | 4241 | namespace.usingnamespace_set.putAssumeCapacity(new_decl_index, declaration.flags.is_pub); |
| 4275 | } | 4242 | } |
| 4276 | new_decl.src_line = line; | 4243 | new_decl.src_line = line; |
| 4277 | gop.key_ptr.* = new_decl_index; | 4244 | gop.key_ptr.* = new_decl_index; |
| 4278 | // Exported decls, comptime decls, usingnamespace decls, and | 4245 | // Exported decls, comptime decls, usingnamespace decls, and |
| 4279 | // test decls if in test mode, get analyzed. | 4246 | // test decls if in test mode, get analyzed. |
| 4280 | const decl_mod = namespace.file_scope.mod; | 4247 | const decl_mod = namespace.file_scope.mod; |
| 4281 | const want_analysis = is_exported or switch (decl_name_index) { | 4248 | const want_analysis = declaration.flags.is_export or switch (kind) { |
| 4282 | .empty => true, // comptime or usingnamespace decl | 4249 | .anon => unreachable, |
| 4283 | .unnamed_test_decl => blk: { | 4250 | .@"comptime", .@"usingnamespace" => true, |
| 4284 | // test decl with no name. Skip the part where we check against | 4251 | .named => false, |
| 4285 | // the test name filter. | 4252 | .@"test" => a: { |
| 4286 | if (!comp.config.is_test) break :blk false; | 4253 | if (!comp.config.is_test) break :a false; |
| 4287 | if (decl_mod != mod.main_mod) break :blk false; | 4254 | if (decl_mod != zcu.main_mod) break :a false; |
| 4288 | try mod.test_functions.put(gpa, new_decl_index, {}); | 4255 | if (is_named_test) { |
| 4289 | break :blk true; | 4256 | if (comp.test_filter) |test_filter| { |
| 4290 | }, | 4257 | if (mem.indexOf(u8, ip.stringToSlice(decl_name), test_filter) == null) { |
| 4291 | else => blk: { | 4258 | break :a false; |
| 4292 | if (!is_named_test) break :blk false; | 4259 | } |
| 4293 | if (!comp.config.is_test) break :blk false; | ||
| 4294 | if (decl_mod != mod.main_mod) break :blk false; | ||
| 4295 | if (comp.test_filter) |test_filter| { | ||
| 4296 | if (mem.indexOf(u8, ip.stringToSlice(decl_name), test_filter) == null) { | ||
| 4297 | break :blk false; | ||
| 4298 | } | 4260 | } |
| 4299 | } | 4261 | } |
| 4300 | try mod.test_functions.put(gpa, new_decl_index, {}); | 4262 | try zcu.test_functions.put(gpa, new_decl_index, {}); |
| 4301 | break :blk true; | 4263 | break :a true; |
| 4302 | }, | 4264 | }, |
| 4303 | }; | 4265 | }; |
| 4304 | if (want_analysis) { | 4266 | if (want_analysis) { |
| ... | @@ -4307,46 +4269,42 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err | ... | @@ -4307,46 +4269,42 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err |
| 4307 | }); | 4269 | }); |
| 4308 | comp.work_queue.writeItemAssumeCapacity(.{ .analyze_decl = new_decl_index }); | 4270 | comp.work_queue.writeItemAssumeCapacity(.{ .analyze_decl = new_decl_index }); |
| 4309 | } | 4271 | } |
| 4310 | new_decl.is_pub = is_pub; | 4272 | new_decl.is_pub = declaration.flags.is_pub; |
| 4311 | new_decl.is_exported = is_exported; | 4273 | new_decl.is_exported = declaration.flags.is_export; |
| 4312 | new_decl.has_align = has_align; | 4274 | new_decl.zir_decl_index = decl_inst.toOptional(); |
| 4313 | new_decl.has_linksection_or_addrspace = has_linksection_or_addrspace; | ||
| 4314 | new_decl.zir_decl_index = @enumFromInt(decl_sub_index); | ||
| 4315 | new_decl.alive = true; // This Decl corresponds to an AST node and therefore always alive. | 4275 | new_decl.alive = true; // This Decl corresponds to an AST node and therefore always alive. |
| 4316 | return; | 4276 | return; |
| 4317 | } | 4277 | } |
| 4318 | const decl_index = gop.key_ptr.*; | 4278 | const decl_index = gop.key_ptr.*; |
| 4319 | const decl = mod.declPtr(decl_index); | 4279 | const decl = zcu.declPtr(decl_index); |
| 4320 | if (kind == .@"test") { | 4280 | if (kind == .@"test") { |
| 4321 | const src_loc = SrcLoc{ | 4281 | const src_loc = SrcLoc{ |
| 4322 | .file_scope = decl.getFileScope(mod), | 4282 | .file_scope = decl.getFileScope(zcu), |
| 4323 | .parent_decl_node = decl.src_node, | 4283 | .parent_decl_node = decl.src_node, |
| 4324 | .lazy = .{ .token_offset = 1 }, | 4284 | .lazy = .{ .token_offset = 1 }, |
| 4325 | }; | 4285 | }; |
| 4326 | const msg = try ErrorMsg.create(gpa, src_loc, "duplicate test name: {}", .{ | 4286 | const msg = try ErrorMsg.create(gpa, src_loc, "duplicate test name: {}", .{ |
| 4327 | decl_name.fmt(&mod.intern_pool), | 4287 | decl_name.fmt(ip), |
| 4328 | }); | 4288 | }); |
| 4329 | errdefer msg.destroy(gpa); | 4289 | errdefer msg.destroy(gpa); |
| 4330 | try mod.failed_decls.putNoClobber(gpa, decl_index, msg); | 4290 | try zcu.failed_decls.putNoClobber(gpa, decl_index, msg); |
| 4331 | const other_src_loc = SrcLoc{ | 4291 | const other_src_loc = SrcLoc{ |
| 4332 | .file_scope = namespace.file_scope, | 4292 | .file_scope = namespace.file_scope, |
| 4333 | .parent_decl_node = decl_node, | 4293 | .parent_decl_node = decl_node, |
| 4334 | .lazy = .{ .token_offset = 1 }, | 4294 | .lazy = .{ .token_offset = 1 }, |
| 4335 | }; | 4295 | }; |
| 4336 | try mod.errNoteNonLazy(other_src_loc, msg, "other test here", .{}); | 4296 | try zcu.errNoteNonLazy(other_src_loc, msg, "other test here", .{}); |
| 4337 | } | 4297 | } |
| 4338 | // Update the AST node of the decl; even if its contents are unchanged, it may | 4298 | // Update the AST node of the decl; even if its contents are unchanged, it may |
| 4339 | // have been re-ordered. | 4299 | // have been re-ordered. |
| 4340 | decl.src_node = decl_node; | 4300 | decl.src_node = decl_node; |
| 4341 | decl.src_line = line; | 4301 | decl.src_line = line; |
| 4342 | 4302 | ||
| 4343 | decl.is_pub = is_pub; | 4303 | decl.is_pub = declaration.flags.is_pub; |
| 4344 | decl.is_exported = is_exported; | 4304 | decl.is_exported = declaration.flags.is_export; |
| 4345 | decl.kind = kind; | 4305 | decl.kind = kind; |
| 4346 | decl.has_align = has_align; | 4306 | decl.zir_decl_index = decl_inst.toOptional(); |
| 4347 | decl.has_linksection_or_addrspace = has_linksection_or_addrspace; | 4307 | if (decl.getOwnedFunction(zcu) != null) { |
| 4348 | decl.zir_decl_index = @enumFromInt(decl_sub_index); | ||
| 4349 | if (decl.getOwnedFunction(mod) != null) { | ||
| 4350 | // TODO Look into detecting when this would be unnecessary by storing enough state | 4308 | // TODO Look into detecting when this would be unnecessary by storing enough state |
| 4351 | // in `Decl` to notice that the line number did not change. | 4309 | // in `Decl` to notice that the line number did not change. |
| 4352 | comp.work_queue.writeItemAssumeCapacity(.{ .update_line_number = decl_index }); | 4310 | comp.work_queue.writeItemAssumeCapacity(.{ .update_line_number = decl_index }); |
| ... | @@ -4730,8 +4688,6 @@ pub fn allocateNewDecl( | ... | @@ -4730,8 +4688,6 @@ pub fn allocateNewDecl( |
| 4730 | .generation = 0, | 4688 | .generation = 0, |
| 4731 | .is_pub = false, | 4689 | .is_pub = false, |
| 4732 | .is_exported = false, | 4690 | .is_exported = false, |
| 4733 | .has_linksection_or_addrspace = false, | ||
| 4734 | .has_align = false, | ||
| 4735 | .alive = false, | 4691 | .alive = false, |
| 4736 | .kind = .anon, | 4692 | .kind = .anon, |
| 4737 | }); | 4693 | }); |
src/Sema.zig+20-12| ... | @@ -1224,6 +1224,10 @@ fn analyzeBodyInner( | ... | @@ -1224,6 +1224,10 @@ fn analyzeBodyInner( |
| 1224 | .trap => break sema.zirTrap(block, inst), | 1224 | .trap => break sema.zirTrap(block, inst), |
| 1225 | // zig fmt: on | 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 | .extended => ext: { | 1231 | .extended => ext: { |
| 1228 | const extended = datas[@intFromEnum(inst)].extended; | 1232 | const extended = datas[@intFromEnum(inst)].extended; |
| 1229 | break :ext switch (extended.opcode) { | 1233 | break :ext switch (extended.opcode) { |
| ... | @@ -2736,7 +2740,9 @@ pub fn getStructType( | ... | @@ -2736,7 +2740,9 @@ pub fn getStructType( |
| 2736 | } | 2740 | } |
| 2737 | } | 2741 | } |
| 2738 | 2742 | ||
| 2739 | extra_index = try mod.scanNamespace(namespace, extra_index, decls_len, mod.declPtr(decl)); | 2743 | const decls = sema.code.bodySlice(extra_index, decls_len); |
| 2744 | try mod.scanNamespace(namespace, decls, mod.declPtr(decl)); | ||
| 2745 | extra_index += decls_len; | ||
| 2740 | 2746 | ||
| 2741 | const ty = try ip.getStructType(gpa, .{ | 2747 | const ty = try ip.getStructType(gpa, .{ |
| 2742 | .decl = decl, | 2748 | .decl = decl, |
| ... | @@ -2973,7 +2979,9 @@ fn zirEnumDecl( | ... | @@ -2973,7 +2979,9 @@ fn zirEnumDecl( |
| 2973 | const new_namespace = mod.namespacePtr(new_namespace_index); | 2979 | const new_namespace = mod.namespacePtr(new_namespace_index); |
| 2974 | errdefer if (!done) mod.destroyNamespace(new_namespace_index); | 2980 | errdefer if (!done) mod.destroyNamespace(new_namespace_index); |
| 2975 | 2981 | ||
| 2976 | extra_index = try mod.scanNamespace(new_namespace_index, extra_index, decls_len, new_decl); | 2982 | const decls = sema.code.bodySlice(extra_index, decls_len); |
| 2983 | try mod.scanNamespace(new_namespace_index, decls, new_decl); | ||
| 2984 | extra_index += decls_len; | ||
| 2977 | 2985 | ||
| 2978 | const body = sema.code.bodySlice(extra_index, body_len); | 2986 | const body = sema.code.bodySlice(extra_index, body_len); |
| 2979 | extra_index += body.len; | 2987 | extra_index += body.len; |
| ... | @@ -3263,7 +3271,8 @@ fn zirUnionDecl( | ... | @@ -3263,7 +3271,8 @@ fn zirUnionDecl( |
| 3263 | new_decl.val = Value.fromInterned(union_ty); | 3271 | new_decl.val = Value.fromInterned(union_ty); |
| 3264 | new_namespace.ty = Type.fromInterned(union_ty); | 3272 | new_namespace.ty = Type.fromInterned(union_ty); |
| 3265 | 3273 | ||
| 3266 | _ = try mod.scanNamespace(new_namespace_index, extra_index, decls_len, new_decl); | 3274 | const decls = sema.code.bodySlice(extra_index, decls_len); |
| 3275 | try mod.scanNamespace(new_namespace_index, decls, new_decl); | ||
| 3267 | 3276 | ||
| 3268 | const decl_val = sema.analyzeDeclVal(block, src, new_decl_index); | 3277 | const decl_val = sema.analyzeDeclVal(block, src, new_decl_index); |
| 3269 | try mod.finalizeAnonDecl(new_decl_index); | 3278 | try mod.finalizeAnonDecl(new_decl_index); |
| ... | @@ -3326,7 +3335,8 @@ fn zirOpaqueDecl( | ... | @@ -3326,7 +3335,8 @@ fn zirOpaqueDecl( |
| 3326 | new_decl.val = Value.fromInterned(opaque_ty); | 3335 | new_decl.val = Value.fromInterned(opaque_ty); |
| 3327 | new_namespace.ty = Type.fromInterned(opaque_ty); | 3336 | new_namespace.ty = Type.fromInterned(opaque_ty); |
| 3328 | 3337 | ||
| 3329 | extra_index = try mod.scanNamespace(new_namespace_index, extra_index, decls_len, new_decl); | 3338 | const decls = sema.code.bodySlice(extra_index, decls_len); |
| 3339 | try mod.scanNamespace(new_namespace_index, decls, new_decl); | ||
| 3330 | 3340 | ||
| 3331 | const decl_val = sema.analyzeDeclVal(block, src, new_decl_index); | 3341 | const decl_val = sema.analyzeDeclVal(block, src, new_decl_index); |
| 3332 | try mod.finalizeAnonDecl(new_decl_index); | 3342 | try mod.finalizeAnonDecl(new_decl_index); |
| ... | @@ -36331,9 +36341,7 @@ fn structZirInfo(zir: Zir, zir_index: Zir.Inst.Index) struct { | ... | @@ -36331,9 +36341,7 @@ fn structZirInfo(zir: Zir, zir_index: Zir.Inst.Index) struct { |
| 36331 | } | 36341 | } |
| 36332 | 36342 | ||
| 36333 | // Skip over decls. | 36343 | // Skip over decls. |
| 36334 | var decls_it = zir.declIteratorInner(extra_index, decls_len); | 36344 | extra_index += decls_len; |
| 36335 | while (decls_it.next()) |_| {} | ||
| 36336 | extra_index = decls_it.extra_index; | ||
| 36337 | 36345 | ||
| 36338 | return .{ fields_len, small, extra_index }; | 36346 | return .{ fields_len, small, extra_index }; |
| 36339 | } | 36347 | } |
| ... | @@ -36802,9 +36810,7 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Key.Un | ... | @@ -36802,9 +36810,7 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Key.Un |
| 36802 | } else 0; | 36810 | } else 0; |
| 36803 | 36811 | ||
| 36804 | // Skip over decls. | 36812 | // Skip over decls. |
| 36805 | var decls_it = zir.declIteratorInner(extra_index, decls_len); | 36813 | extra_index += decls_len; |
| 36806 | while (decls_it.next()) |_| {} | ||
| 36807 | extra_index = decls_it.extra_index; | ||
| 36808 | 36814 | ||
| 36809 | const body = zir.bodySlice(extra_index, body_len); | 36815 | const body = zir.bodySlice(extra_index, body_len); |
| 36810 | extra_index += body.len; | 36816 | extra_index += body.len; |
| ... | @@ -37801,10 +37807,12 @@ pub fn analyzeAddressSpace( | ... | @@ -37801,10 +37807,12 @@ pub fn analyzeAddressSpace( |
| 37801 | ctx: AddressSpaceContext, | 37807 | ctx: AddressSpaceContext, |
| 37802 | ) !std.builtin.AddressSpace { | 37808 | ) !std.builtin.AddressSpace { |
| 37803 | const mod = sema.mod; | 37809 | const mod = sema.mod; |
| 37804 | const addrspace_tv = try sema.resolveInstConst(block, src, zir_ref, .{ | 37810 | const air_ref = try sema.resolveInst(zir_ref); |
| 37811 | const coerced = try sema.coerce(block, Type.fromInterned(.address_space_type), air_ref, src); | ||
| 37812 | const addrspace_val = try sema.resolveConstDefinedValue(block, src, coerced, .{ | ||
| 37805 | .needed_comptime_reason = "address space must be comptime-known", | 37813 | .needed_comptime_reason = "address space must be comptime-known", |
| 37806 | }); | 37814 | }); |
| 37807 | const address_space = mod.toEnum(std.builtin.AddressSpace, addrspace_tv.val); | 37815 | const address_space = mod.toEnum(std.builtin.AddressSpace, addrspace_val); |
| 37808 | const target = sema.mod.getTarget(); | 37816 | const target = sema.mod.getTarget(); |
| 37809 | const arch = target.cpu.arch; | 37817 | const arch = target.cpu.arch; |
| 37810 | 37818 |
src/Zir.zig+213-187| ... | @@ -30,7 +30,7 @@ instructions: std.MultiArrayList(Inst).Slice, | ... | @@ -30,7 +30,7 @@ instructions: std.MultiArrayList(Inst).Slice, |
| 30 | /// is referencing the data here whether they want to store both index and length, | 30 | /// is referencing the data here whether they want to store both index and length, |
| 31 | /// thus allowing null bytes, or store only index, and use null-termination. The | 31 | /// thus allowing null bytes, or store only index, and use null-termination. The |
| 32 | /// `string_bytes` array is agnostic to either usage. | 32 | /// `string_bytes` array is agnostic to either usage. |
| 33 | /// Indexes 0 and 1 are reserved for special cases. | 33 | /// Index 0 is reserved for special cases. |
| 34 | string_bytes: []u8, | 34 | string_bytes: []u8, |
| 35 | /// The meaning of this data is determined by `Inst.Tag` value. | 35 | /// The meaning of this data is determined by `Inst.Tag` value. |
| 36 | /// The first few indexes are reserved. See `ExtraIndex` for the values. | 36 | /// The first few indexes are reserved. See `ExtraIndex` for the values. |
| ... | @@ -60,21 +60,6 @@ pub const ExtraIndex = enum(u32) { | ... | @@ -60,21 +60,6 @@ pub const ExtraIndex = enum(u32) { |
| 60 | imports, | 60 | imports, |
| 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 | fn ExtraData(comptime T: type) type { | 65 | fn ExtraData(comptime T: type) type { |
| ... | @@ -93,6 +78,7 @@ pub fn extraData(code: Zir, comptime T: type, index: usize) ExtraData(T) { | ... | @@ -93,6 +78,7 @@ pub fn extraData(code: Zir, comptime T: type, index: usize) ExtraData(T) { |
| 93 | 78 | ||
| 94 | Inst.Ref, | 79 | Inst.Ref, |
| 95 | Inst.Index, | 80 | Inst.Index, |
| 81 | Inst.Declaration.Name, | ||
| 96 | NullTerminatedString, | 82 | NullTerminatedString, |
| 97 | => @enumFromInt(code.extra[i]), | 83 | => @enumFromInt(code.extra[i]), |
| 98 | 84 | ||
| ... | @@ -102,6 +88,7 @@ pub fn extraData(code: Zir, comptime T: type, index: usize) ExtraData(T) { | ... | @@ -102,6 +88,7 @@ pub fn extraData(code: Zir, comptime T: type, index: usize) ExtraData(T) { |
| 102 | Inst.SwitchBlock.Bits, | 88 | Inst.SwitchBlock.Bits, |
| 103 | Inst.SwitchBlockErrUnion.Bits, | 89 | Inst.SwitchBlockErrUnion.Bits, |
| 104 | Inst.FuncFancy.Bits, | 90 | Inst.FuncFancy.Bits, |
| 91 | Inst.Declaration.Flags, | ||
| 105 | => @bitCast(code.extra[i]), | 92 | => @bitCast(code.extra[i]), |
| 106 | 93 | ||
| 107 | else => @compileError("bad field type"), | 94 | else => @compileError("bad field type"), |
| ... | @@ -116,8 +103,6 @@ pub fn extraData(code: Zir, comptime T: type, index: usize) ExtraData(T) { | ... | @@ -116,8 +103,6 @@ pub fn extraData(code: Zir, comptime T: type, index: usize) ExtraData(T) { |
| 116 | 103 | ||
| 117 | pub const NullTerminatedString = enum(u32) { | 104 | pub const NullTerminatedString = enum(u32) { |
| 118 | empty = 0, | 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,6 +289,12 @@ pub const Inst = struct { |
| 304 | /// a noreturn instruction. | 289 | /// a noreturn instruction. |
| 305 | /// Uses the `pl_node` union field. Payload is `Block`. | 290 | /// Uses the `pl_node` union field. Payload is `Block`. |
| 306 | block_inline, | 291 | block_inline, |
| 292 | /// This instruction may only ever appear in the list of declarations for a | ||
| 293 | /// namespace type, e.g. within a `struct_decl` instruction. It represents a | ||
| 294 | /// single source declaration (`const`/`var`/`fn`), containing the name, | ||
| 295 | /// attributes, type, and value of the declaration. | ||
| 296 | /// Uses the `pl_node` union field. Payload is `Declaration`. | ||
| 297 | declaration, | ||
| 307 | /// Implements `suspend {...}`. | 298 | /// Implements `suspend {...}`. |
| 308 | /// Uses the `pl_node` union field. Payload is `Block`. | 299 | /// Uses the `pl_node` union field. Payload is `Block`. |
| 309 | suspend_block, | 300 | suspend_block, |
| ... | @@ -1092,6 +1083,7 @@ pub const Inst = struct { | ... | @@ -1092,6 +1083,7 @@ pub const Inst = struct { |
| 1092 | .block, | 1083 | .block, |
| 1093 | .block_comptime, | 1084 | .block_comptime, |
| 1094 | .block_inline, | 1085 | .block_inline, |
| 1086 | .declaration, | ||
| 1095 | .suspend_block, | 1087 | .suspend_block, |
| 1096 | .loop, | 1088 | .loop, |
| 1097 | .bool_br_and, | 1089 | .bool_br_and, |
| ... | @@ -1405,6 +1397,7 @@ pub const Inst = struct { | ... | @@ -1405,6 +1397,7 @@ pub const Inst = struct { |
| 1405 | .block, | 1397 | .block, |
| 1406 | .block_comptime, | 1398 | .block_comptime, |
| 1407 | .block_inline, | 1399 | .block_inline, |
| 1400 | .declaration, | ||
| 1408 | .suspend_block, | 1401 | .suspend_block, |
| 1409 | .loop, | 1402 | .loop, |
| 1410 | .bool_br_and, | 1403 | .bool_br_and, |
| ... | @@ -1639,6 +1632,7 @@ pub const Inst = struct { | ... | @@ -1639,6 +1632,7 @@ pub const Inst = struct { |
| 1639 | .block = .pl_node, | 1632 | .block = .pl_node, |
| 1640 | .block_comptime = .pl_node, | 1633 | .block_comptime = .pl_node, |
| 1641 | .block_inline = .pl_node, | 1634 | .block_inline = .pl_node, |
| 1635 | .declaration = .pl_node, | ||
| 1642 | .suspend_block = .pl_node, | 1636 | .suspend_block = .pl_node, |
| 1643 | .bool_not = .un_node, | 1637 | .bool_not = .un_node, |
| 1644 | .bool_br_and = .bool_br, | 1638 | .bool_br_and = .bool_br, |
| ... | @@ -2508,6 +2502,7 @@ pub const Inst = struct { | ... | @@ -2508,6 +2502,7 @@ pub const Inst = struct { |
| 2508 | /// If this is 1 it means return_type is a simple Ref | 2502 | /// If this is 1 it means return_type is a simple Ref |
| 2509 | ret_body_len: u32, | 2503 | ret_body_len: u32, |
| 2510 | /// Points to the block that contains the param instructions for this function. | 2504 | /// Points to the block that contains the param instructions for this function. |
| 2505 | /// If this is a `declaration`, it refers to the declaration's value body. | ||
| 2511 | param_block: Index, | 2506 | param_block: Index, |
| 2512 | body_len: u32, | 2507 | body_len: u32, |
| 2513 | 2508 | ||
| ... | @@ -2565,6 +2560,7 @@ pub const Inst = struct { | ... | @@ -2565,6 +2560,7 @@ pub const Inst = struct { |
| 2565 | /// 18. src_locs: Func.SrcLocs // if body_len != 0 | 2560 | /// 18. src_locs: Func.SrcLocs // if body_len != 0 |
| 2566 | pub const FuncFancy = struct { | 2561 | pub const FuncFancy = struct { |
| 2567 | /// Points to the block that contains the param instructions for this function. | 2562 | /// Points to the block that contains the param instructions for this function. |
| 2563 | /// If this is a `declaration`, it refers to the declaration's value body. | ||
| 2568 | param_block: Index, | 2564 | param_block: Index, |
| 2569 | body_len: u32, | 2565 | body_len: u32, |
| 2570 | bits: Bits, | 2566 | bits: Bits, |
| ... | @@ -2632,6 +2628,116 @@ pub const Inst = struct { | ... | @@ -2632,6 +2628,116 @@ pub const Inst = struct { |
| 2632 | body_len: u32, | 2628 | body_len: u32, |
| 2633 | }; | 2629 | }; |
| 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 | /// Stored inside extra, with trailing arguments according to `args_len`. | 2741 | /// Stored inside extra, with trailing arguments according to `args_len`. |
| 2636 | /// Implicit 0. arg_0_start: u32, // always same as `args_len` | 2742 | /// Implicit 0. arg_0_start: u32, // always same as `args_len` |
| 2637 | /// 1. arg_end: u32, // for each `args_len` | 2743 | /// 1. arg_end: u32, // for each `args_len` |
| ... | @@ -2913,37 +3019,14 @@ pub const Inst = struct { | ... | @@ -2913,37 +3019,14 @@ pub const Inst = struct { |
| 2913 | /// 3. backing_int_body_len: u32, // if has_backing_int | 3019 | /// 3. backing_int_body_len: u32, // if has_backing_int |
| 2914 | /// 4. backing_int_ref: Ref, // if has_backing_int and backing_int_body_len is 0 | 3020 | /// 4. backing_int_ref: Ref, // if has_backing_int and backing_int_body_len is 0 |
| 2915 | /// 5. backing_int_body_inst: Inst, // if has_backing_int and backing_int_body_len is > 0 | 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 | 3022 | /// 6. decl: Index, // for every decls_len; points to a `declaration` instruction |
| 2917 | /// - sets of 4 bits: | 3023 | /// 7. flags: u32 // for every 8 fields |
| 2918 | /// 0b000X: whether corresponding decl is pub | ||
| 2919 | /// 0b00X0: whether corresponding decl is exported | ||
| 2920 | /// 0b0X00: whether corresponding decl has an align expression | ||
| 2921 | /// 0bX000: whether corresponding decl has a linksection or an address space expression | ||
| 2922 | /// 7. decl: { // for every decls_len | ||
| 2923 | /// src_hash: [4]u32, // hash of source bytes | ||
| 2924 | /// line: u32, // line number of decl, relative to parent | ||
| 2925 | /// name: NullTerminatedString, // null terminated string index | ||
| 2926 | /// - 0 means comptime or usingnamespace decl. | ||
| 2927 | /// - if name == 0 `is_exported` determines which one: 0=comptime,1=usingnamespace | ||
| 2928 | /// - 1 means test decl with no name. | ||
| 2929 | /// - 2 means that the test is a decltest, doc_comment gives the name of the identifier | ||
| 2930 | /// - if there is a 0 byte at the position `name` indexes, it indicates | ||
| 2931 | /// this is a test decl, and the name starts at `name+1`. | ||
| 2932 | /// value: Index, | ||
| 2933 | /// doc_comment: u32, .empty if no doc comment, if this is a decltest, doc_comment references the decl name in the string table | ||
| 2934 | /// align: Ref, // if corresponding bit is set | ||
| 2935 | /// link_section_or_address_space: { // if corresponding bit is set. | ||
| 2936 | /// link_section: Ref, | ||
| 2937 | /// address_space: Ref, | ||
| 2938 | /// } | ||
| 2939 | /// } | ||
| 2940 | /// 8. flags: u32 // for every 8 fields | ||
| 2941 | /// - sets of 4 bits: | 3024 | /// - sets of 4 bits: |
| 2942 | /// 0b000X: whether corresponding field has an align expression | 3025 | /// 0b000X: whether corresponding field has an align expression |
| 2943 | /// 0b00X0: whether corresponding field has a default expression | 3026 | /// 0b00X0: whether corresponding field has a default expression |
| 2944 | /// 0b0X00: whether corresponding field is comptime | 3027 | /// 0b0X00: whether corresponding field is comptime |
| 2945 | /// 0bX000: whether corresponding field has a type expression | 3028 | /// 0bX000: whether corresponding field has a type expression |
| 2946 | /// 9. fields: { // for every fields_len | 3029 | /// 8. fields: { // for every fields_len |
| 2947 | /// field_name: u32, // if !is_tuple | 3030 | /// field_name: u32, // if !is_tuple |
| 2948 | /// doc_comment: NullTerminatedString, // .empty if no doc comment | 3031 | /// doc_comment: NullTerminatedString, // .empty if no doc comment |
| 2949 | /// field_type: Ref, // if corresponding bit is not set. none means anytype. | 3032 | /// field_type: Ref, // if corresponding bit is not set. none means anytype. |
| ... | @@ -3009,33 +3092,11 @@ pub const Inst = struct { | ... | @@ -3009,33 +3092,11 @@ pub const Inst = struct { |
| 3009 | /// 2. body_len: u32, // if has_body_len | 3092 | /// 2. body_len: u32, // if has_body_len |
| 3010 | /// 3. fields_len: u32, // if has_fields_len | 3093 | /// 3. fields_len: u32, // if has_fields_len |
| 3011 | /// 4. decls_len: u32, // if has_decls_len | 3094 | /// 4. decls_len: u32, // if has_decls_len |
| 3012 | /// 5. decl_bits: u32 // for every 8 decls | 3095 | /// 5. decl: Index, // for every decls_len; points to a `declaration` instruction |
| 3013 | /// - sets of 4 bits: | 3096 | /// 6. inst: Index // for every body_len |
| 3014 | /// 0b000X: whether corresponding decl is pub | 3097 | /// 7. has_bits: u32 // for every 32 fields |
| 3015 | /// 0b00X0: whether corresponding decl is exported | ||
| 3016 | /// 0b0X00: whether corresponding decl has an align expression | ||
| 3017 | /// 0bX000: whether corresponding decl has a linksection or an address space expression | ||
| 3018 | /// 6. decl: { // for every decls_len | ||
| 3019 | /// src_hash: [4]u32, // hash of source bytes | ||
| 3020 | /// line: u32, // line number of decl, relative to parent | ||
| 3021 | /// name: NullTerminatedString, // null terminated string index | ||
| 3022 | /// - 0 means comptime or usingnamespace decl. | ||
| 3023 | /// - if name == 0 `is_exported` determines which one: 0=comptime,1=usingnamespace | ||
| 3024 | /// - 1 means test decl with no name. | ||
| 3025 | /// - if there is a 0 byte at the position `name` indexes, it indicates | ||
| 3026 | /// this is a test decl, and the name starts at `name+1`. | ||
| 3027 | /// value: Index, | ||
| 3028 | /// doc_comment: u32, // .empty if no doc_comment | ||
| 3029 | /// align: Ref, // if corresponding bit is set | ||
| 3030 | /// link_section_or_address_space: { // if corresponding bit is set. | ||
| 3031 | /// link_section: Ref, | ||
| 3032 | /// address_space: Ref, | ||
| 3033 | /// } | ||
| 3034 | /// } | ||
| 3035 | /// 7. inst: Index // for every body_len | ||
| 3036 | /// 8. has_bits: u32 // for every 32 fields | ||
| 3037 | /// - the bit is whether corresponding field has an value expression | 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 | /// field_name: u32, | 3100 | /// field_name: u32, |
| 3040 | /// doc_comment: u32, // .empty if no doc_comment | 3101 | /// doc_comment: u32, // .empty if no doc_comment |
| 3041 | /// value: Ref, // if corresponding bit is set | 3102 | /// value: Ref, // if corresponding bit is set |
| ... | @@ -3059,37 +3120,15 @@ pub const Inst = struct { | ... | @@ -3059,37 +3120,15 @@ pub const Inst = struct { |
| 3059 | /// 2. body_len: u32, // if has_body_len | 3120 | /// 2. body_len: u32, // if has_body_len |
| 3060 | /// 3. fields_len: u32, // if has_fields_len | 3121 | /// 3. fields_len: u32, // if has_fields_len |
| 3061 | /// 4. decls_len: u32, // if has_decls_len | 3122 | /// 4. decls_len: u32, // if has_decls_len |
| 3062 | /// 5. decl_bits: u32 // for every 8 decls | 3123 | /// 5. decl: Index, // for every decls_len; points to a `declaration` instruction |
| 3063 | /// - sets of 4 bits: | 3124 | /// 6. inst: Index // for every body_len |
| 3064 | /// 0b000X: whether corresponding decl is pub | 3125 | /// 7. has_bits: u32 // for every 8 fields |
| 3065 | /// 0b00X0: whether corresponding decl is exported | ||
| 3066 | /// 0b0X00: whether corresponding decl has an align expression | ||
| 3067 | /// 0bX000: whether corresponding decl has a linksection or an address space expression | ||
| 3068 | /// 6. decl: { // for every decls_len | ||
| 3069 | /// src_hash: [4]u32, // hash of source bytes | ||
| 3070 | /// line: u32, // line number of decl, relative to parent | ||
| 3071 | /// name: NullTerminatedString, // null terminated string index | ||
| 3072 | /// - 0 means comptime or usingnamespace decl. | ||
| 3073 | /// - if name == 0 `is_exported` determines which one: 0=comptime,1=usingnamespace | ||
| 3074 | /// - 1 means test decl with no name. | ||
| 3075 | /// - if there is a 0 byte at the position `name` indexes, it indicates | ||
| 3076 | /// this is a test decl, and the name starts at `name+1`. | ||
| 3077 | /// value: Index, | ||
| 3078 | /// doc_comment: NullTerminatedString, // .empty if no doc comment | ||
| 3079 | /// align: Ref, // if corresponding bit is set | ||
| 3080 | /// link_section_or_address_space: { // if corresponding bit is set. | ||
| 3081 | /// link_section: Ref, | ||
| 3082 | /// address_space: Ref, | ||
| 3083 | /// } | ||
| 3084 | /// } | ||
| 3085 | /// 7. inst: Index // for every body_len | ||
| 3086 | /// 8. has_bits: u32 // for every 8 fields | ||
| 3087 | /// - sets of 4 bits: | 3126 | /// - sets of 4 bits: |
| 3088 | /// 0b000X: whether corresponding field has a type expression | 3127 | /// 0b000X: whether corresponding field has a type expression |
| 3089 | /// 0b00X0: whether corresponding field has a align expression | 3128 | /// 0b00X0: whether corresponding field has a align expression |
| 3090 | /// 0b0X00: whether corresponding field has a tag value expression | 3129 | /// 0b0X00: whether corresponding field has a tag value expression |
| 3091 | /// 0bX000: unused | 3130 | /// 0bX000: unused |
| 3092 | /// 9. fields: { // for every fields_len | 3131 | /// 8. fields: { // for every fields_len |
| 3093 | /// field_name: NullTerminatedString, // null terminated string index | 3132 | /// field_name: NullTerminatedString, // null terminated string index |
| 3094 | /// doc_comment: NullTerminatedString, // .empty if no doc comment | 3133 | /// doc_comment: NullTerminatedString, // .empty if no doc comment |
| 3095 | /// field_type: Ref, // if corresponding bit is set | 3134 | /// field_type: Ref, // if corresponding bit is set |
| ... | @@ -3121,29 +3160,7 @@ pub const Inst = struct { | ... | @@ -3121,29 +3160,7 @@ pub const Inst = struct { |
| 3121 | /// Trailing: | 3160 | /// Trailing: |
| 3122 | /// 0. src_node: i32, // if has_src_node | 3161 | /// 0. src_node: i32, // if has_src_node |
| 3123 | /// 1. decls_len: u32, // if has_decls_len | 3162 | /// 1. decls_len: u32, // if has_decls_len |
| 3124 | /// 2. decl_bits: u32 // for every 8 decls | 3163 | /// 2. decl: Index, // for every decls_len; points to a `declaration` instruction |
| 3125 | /// - sets of 4 bits: | ||
| 3126 | /// 0b000X: whether corresponding decl is pub | ||
| 3127 | /// 0b00X0: whether corresponding decl is exported | ||
| 3128 | /// 0b0X00: whether corresponding decl has an align expression | ||
| 3129 | /// 0bX000: whether corresponding decl has a linksection or an address space expression | ||
| 3130 | /// 3. decl: { // for every decls_len | ||
| 3131 | /// src_hash: [4]u32, // hash of source bytes | ||
| 3132 | /// line: u32, // line number of decl, relative to parent | ||
| 3133 | /// name: NullTerminatedString, // null terminated string index | ||
| 3134 | /// - 0 means comptime or usingnamespace decl. | ||
| 3135 | /// - if name == 0 `is_exported` determines which one: 0=comptime,1=usingnamespace | ||
| 3136 | /// - 1 means test decl with no name. | ||
| 3137 | /// - if there is a 0 byte at the position `name` indexes, it indicates | ||
| 3138 | /// this is a test decl, and the name starts at `name+1`. | ||
| 3139 | /// value: Index, | ||
| 3140 | /// doc_comment: NullTerminatedString, // .empty if no doc comment, | ||
| 3141 | /// align: Ref, // if corresponding bit is set | ||
| 3142 | /// link_section_or_address_space: { // if corresponding bit is set. | ||
| 3143 | /// link_section: Ref, | ||
| 3144 | /// address_space: Ref, | ||
| 3145 | /// } | ||
| 3146 | /// } | ||
| 3147 | pub const OpaqueDecl = struct { | 3164 | pub const OpaqueDecl = struct { |
| 3148 | pub const Small = packed struct { | 3165 | pub const Small = packed struct { |
| 3149 | has_src_node: bool, | 3166 | has_src_node: bool, |
| ... | @@ -3407,44 +3424,17 @@ pub const Inst = struct { | ... | @@ -3407,44 +3424,17 @@ pub const Inst = struct { |
| 3407 | pub const SpecialProng = enum { none, @"else", under }; | 3424 | pub const SpecialProng = enum { none, @"else", under }; |
| 3408 | 3425 | ||
| 3409 | pub const DeclIterator = struct { | 3426 | pub const DeclIterator = struct { |
| 3410 | extra_index: usize, | 3427 | extra_index: u32, |
| 3411 | bit_bag_index: usize, | 3428 | decls_remaining: u32, |
| 3412 | cur_bit_bag: u32, | ||
| 3413 | decl_i: u32, | ||
| 3414 | decls_len: u32, | ||
| 3415 | zir: Zir, | 3429 | zir: Zir, |
| 3416 | 3430 | ||
| 3417 | pub const Item = struct { | 3431 | pub fn next(it: *DeclIterator) ?Inst.Index { |
| 3418 | name: [:0]const u8, | 3432 | if (it.decls_remaining == 0) return null; |
| 3419 | sub_index: ExtraIndex, | 3433 | const decl_inst: Zir.Inst.Index = @enumFromInt(it.zir.extra[it.extra_index]); |
| 3420 | flags: u4, | 3434 | it.extra_index += 1; |
| 3421 | }; | 3435 | it.decls_remaining -= 1; |
| 3422 | 3436 | assert(it.zir.instructions.items(.tag)[@intFromEnum(decl_inst)] == .declaration); | |
| 3423 | pub fn next(it: *DeclIterator) ?Item { | 3437 | return decl_inst; |
| 3424 | if (it.decl_i >= it.decls_len) return null; | ||
| 3425 | |||
| 3426 | if (it.decl_i % 8 == 0) { | ||
| 3427 | it.cur_bit_bag = it.zir.extra[it.bit_bag_index]; | ||
| 3428 | it.bit_bag_index += 1; | ||
| 3429 | } | ||
| 3430 | it.decl_i += 1; | ||
| 3431 | |||
| 3432 | const flags: u4 = @truncate(it.cur_bit_bag); | ||
| 3433 | it.cur_bit_bag >>= 4; | ||
| 3434 | |||
| 3435 | const sub_index: ExtraIndex = @enumFromInt(it.extra_index); | ||
| 3436 | it.extra_index += 5; // src_hash(4) + line(1) | ||
| 3437 | const name = it.zir.nullTerminatedString(@enumFromInt(it.zir.extra[it.extra_index])); | ||
| 3438 | it.extra_index += 3; // name(1) + value(1) + doc_comment(1) | ||
| 3439 | it.extra_index += @as(u1, @truncate(flags >> 2)); // align | ||
| 3440 | it.extra_index += @as(u1, @truncate(flags >> 3)); // link_section | ||
| 3441 | it.extra_index += @as(u1, @truncate(flags >> 3)); // address_space | ||
| 3442 | |||
| 3443 | return Item{ | ||
| 3444 | .sub_index = sub_index, | ||
| 3445 | .name = name, | ||
| 3446 | .flags = flags, | ||
| 3447 | }; | ||
| 3448 | } | 3438 | } |
| 3449 | }; | 3439 | }; |
| 3450 | 3440 | ||
| ... | @@ -3454,14 +3444,18 @@ pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator { | ... | @@ -3454,14 +3444,18 @@ pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator { |
| 3454 | switch (tags[@intFromEnum(decl_inst)]) { | 3444 | switch (tags[@intFromEnum(decl_inst)]) { |
| 3455 | // Functions are allowed and yield no iterations. | 3445 | // Functions are allowed and yield no iterations. |
| 3456 | // There is one case matching this in the extended instruction set below. | 3446 | // There is one case matching this in the extended instruction set below. |
| 3457 | .func, .func_inferred, .func_fancy => return declIteratorInner(zir, 0, 0), | 3447 | .func, .func_inferred, .func_fancy => return .{ |
| 3448 | .extra_index = undefined, | ||
| 3449 | .decls_remaining = 0, | ||
| 3450 | .zir = zir, | ||
| 3451 | }, | ||
| 3458 | 3452 | ||
| 3459 | .extended => { | 3453 | .extended => { |
| 3460 | const extended = datas[@intFromEnum(decl_inst)].extended; | 3454 | const extended = datas[@intFromEnum(decl_inst)].extended; |
| 3461 | switch (extended.opcode) { | 3455 | switch (extended.opcode) { |
| 3462 | .struct_decl => { | 3456 | .struct_decl => { |
| 3463 | const small: Inst.StructDecl.Small = @bitCast(extended.small); | 3457 | const small: Inst.StructDecl.Small = @bitCast(extended.small); |
| 3464 | var extra_index: usize = extended.operand; | 3458 | var extra_index: u32 = extended.operand; |
| 3465 | extra_index += @intFromBool(small.has_src_node); | 3459 | extra_index += @intFromBool(small.has_src_node); |
| 3466 | extra_index += @intFromBool(small.has_fields_len); | 3460 | extra_index += @intFromBool(small.has_fields_len); |
| 3467 | const decls_len = if (small.has_decls_len) decls_len: { | 3461 | const decls_len = if (small.has_decls_len) decls_len: { |
| ... | @@ -3480,11 +3474,15 @@ pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator { | ... | @@ -3480,11 +3474,15 @@ pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator { |
| 3480 | } | 3474 | } |
| 3481 | } | 3475 | } |
| 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 | .enum_decl => { | 3483 | .enum_decl => { |
| 3486 | const small: Inst.EnumDecl.Small = @bitCast(extended.small); | 3484 | const small: Inst.EnumDecl.Small = @bitCast(extended.small); |
| 3487 | var extra_index: usize = extended.operand; | 3485 | var extra_index: u32 = extended.operand; |
| 3488 | extra_index += @intFromBool(small.has_src_node); | 3486 | extra_index += @intFromBool(small.has_src_node); |
| 3489 | extra_index += @intFromBool(small.has_tag_type); | 3487 | extra_index += @intFromBool(small.has_tag_type); |
| 3490 | extra_index += @intFromBool(small.has_body_len); | 3488 | extra_index += @intFromBool(small.has_body_len); |
| ... | @@ -3495,11 +3493,15 @@ pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator { | ... | @@ -3495,11 +3493,15 @@ pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator { |
| 3495 | break :decls_len decls_len; | 3493 | break :decls_len decls_len; |
| 3496 | } else 0; | 3494 | } else 0; |
| 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 | .union_decl => { | 3502 | .union_decl => { |
| 3501 | const small: Inst.UnionDecl.Small = @bitCast(extended.small); | 3503 | const small: Inst.UnionDecl.Small = @bitCast(extended.small); |
| 3502 | var extra_index: usize = extended.operand; | 3504 | var extra_index: u32 = extended.operand; |
| 3503 | extra_index += @intFromBool(small.has_src_node); | 3505 | extra_index += @intFromBool(small.has_src_node); |
| 3504 | extra_index += @intFromBool(small.has_tag_type); | 3506 | extra_index += @intFromBool(small.has_tag_type); |
| 3505 | extra_index += @intFromBool(small.has_body_len); | 3507 | extra_index += @intFromBool(small.has_body_len); |
| ... | @@ -3510,11 +3512,15 @@ pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator { | ... | @@ -3510,11 +3512,15 @@ pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator { |
| 3510 | break :decls_len decls_len; | 3512 | break :decls_len decls_len; |
| 3511 | } else 0; | 3513 | } else 0; |
| 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 | .opaque_decl => { | 3521 | .opaque_decl => { |
| 3516 | const small: Inst.OpaqueDecl.Small = @bitCast(extended.small); | 3522 | const small: Inst.OpaqueDecl.Small = @bitCast(extended.small); |
| 3517 | var extra_index: usize = extended.operand; | 3523 | var extra_index: u32 = extended.operand; |
| 3518 | extra_index += @intFromBool(small.has_src_node); | 3524 | extra_index += @intFromBool(small.has_src_node); |
| 3519 | const decls_len = if (small.has_decls_len) decls_len: { | 3525 | const decls_len = if (small.has_decls_len) decls_len: { |
| 3520 | const decls_len = zir.extra[extra_index]; | 3526 | const decls_len = zir.extra[extra_index]; |
| ... | @@ -3522,7 +3528,11 @@ pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator { | ... | @@ -3522,7 +3528,11 @@ pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator { |
| 3522 | break :decls_len decls_len; | 3528 | break :decls_len decls_len; |
| 3523 | } else 0; | 3529 | } else 0; |
| 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 | else => unreachable, | 3537 | else => unreachable, |
| 3528 | } | 3538 | } |
| ... | @@ -3531,25 +3541,17 @@ pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator { | ... | @@ -3531,25 +3541,17 @@ pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator { |
| 3531 | } | 3541 | } |
| 3532 | } | 3542 | } |
| 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 | /// The iterator would have to allocate memory anyway to iterate. So here we populate | 3544 | /// The iterator would have to allocate memory anyway to iterate. So here we populate |
| 3547 | /// an ArrayList as the result. | 3545 | /// an ArrayList as the result. |
| 3548 | pub fn findDecls(zir: Zir, list: *std.ArrayList(Inst.Index), decl_sub_index: ExtraIndex) !void { | 3546 | pub fn findDecls(zir: Zir, list: *std.ArrayList(Inst.Index), decl_inst: Zir.Inst.Index) !void { |
| 3549 | const block_inst: Zir.Inst.Index = @enumFromInt(zir.extra[@intFromEnum(decl_sub_index) + 6]); | ||
| 3550 | list.clearRetainingCapacity(); | 3547 | list.clearRetainingCapacity(); |
| 3548 | const declaration, const extra_end = zir.getDeclaration(decl_inst); | ||
| 3549 | const bodies = declaration.getBodies(extra_end, zir); | ||
| 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 | fn findDeclsInner( | 3557 | fn findDeclsInner( |
| ... | @@ -3791,8 +3793,17 @@ pub fn getParamBody(zir: Zir, fn_inst: Inst.Index) []const Zir.Inst.Index { | ... | @@ -3791,8 +3793,17 @@ pub fn getParamBody(zir: Zir, fn_inst: Inst.Index) []const Zir.Inst.Index { |
| 3791 | else => unreachable, | 3793 | else => unreachable, |
| 3792 | }; | 3794 | }; |
| 3793 | 3795 | ||
| 3794 | const param_block = zir.extraData(Inst.Block, datas[@intFromEnum(param_block_index)].pl_node.payload_index); | 3796 | switch (tags[@intFromEnum(param_block_index)]) { |
| 3795 | return zir.bodySlice(param_block.end, param_block.data.body_len); | 3797 | .block, .block_comptime, .block_inline => { |
| 3798 | const param_block = zir.extraData(Inst.Block, datas[@intFromEnum(param_block_index)].pl_node.payload_index); | ||
| 3799 | return zir.bodySlice(param_block.end, param_block.data.body_len); | ||
| 3800 | }, | ||
| 3801 | .declaration => { | ||
| 3802 | const decl, const extra_end = zir.getDeclaration(param_block_index); | ||
| 3803 | return decl.getBodies(extra_end, zir).value_body; | ||
| 3804 | }, | ||
| 3805 | else => unreachable, | ||
| 3806 | } | ||
| 3796 | } | 3807 | } |
| 3797 | 3808 | ||
| 3798 | pub fn getFnInfo(zir: Zir, fn_inst: Inst.Index) FnInfo { | 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,12 +3899,17 @@ pub fn getFnInfo(zir: Zir, fn_inst: Inst.Index) FnInfo { |
| 3888 | }, | 3899 | }, |
| 3889 | else => unreachable, | 3900 | else => unreachable, |
| 3890 | }; | 3901 | }; |
| 3891 | switch (tags[@intFromEnum(info.param_block)]) { | 3902 | const param_body = switch (tags[@intFromEnum(info.param_block)]) { |
| 3892 | .block, .block_comptime, .block_inline => {}, // OK | 3903 | .block, .block_comptime, .block_inline => param_body: { |
| 3893 | else => unreachable, // assertion failure | 3904 | const param_block = zir.extraData(Inst.Block, datas[@intFromEnum(info.param_block)].pl_node.payload_index); |
| 3894 | } | 3905 | break :param_body zir.bodySlice(param_block.end, param_block.data.body_len); |
| 3895 | const param_block = zir.extraData(Inst.Block, datas[@intFromEnum(info.param_block)].pl_node.payload_index); | 3906 | }, |
| 3896 | const param_body = zir.bodySlice(param_block.end, param_block.data.body_len); | 3907 | .declaration => param_body: { |
| 3908 | const decl, const extra_end = zir.getDeclaration(info.param_block); | ||
| 3909 | break :param_body decl.getBodies(extra_end, zir).value_body; | ||
| 3910 | }, | ||
| 3911 | else => unreachable, | ||
| 3912 | }; | ||
| 3897 | var total_params_len: u32 = 0; | 3913 | var total_params_len: u32 = 0; |
| 3898 | for (param_body) |inst| { | 3914 | for (param_body) |inst| { |
| 3899 | switch (tags[@intFromEnum(inst)]) { | 3915 | switch (tags[@intFromEnum(inst)]) { |
| ... | @@ -3912,3 +3928,13 @@ pub fn getFnInfo(zir: Zir, fn_inst: Inst.Index) FnInfo { | ... | @@ -3912,3 +3928,13 @@ pub fn getFnInfo(zir: Zir, fn_inst: Inst.Index) FnInfo { |
| 3912 | .total_params_len = total_params_len, | 3928 | .total_params_len = total_params_len, |
| 3913 | }; | 3929 | }; |
| 3914 | } | 3930 | } |
| 3931 | |||
| 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| ... | @@ -6856,10 +6856,7 @@ pub fn cmdChangelist( | ... | @@ -6856,10 +6856,7 @@ pub fn cmdChangelist( |
| 6856 | var inst_map: std.AutoHashMapUnmanaged(Zir.Inst.Index, Zir.Inst.Index) = .{}; | 6856 | var inst_map: std.AutoHashMapUnmanaged(Zir.Inst.Index, Zir.Inst.Index) = .{}; |
| 6857 | defer inst_map.deinit(gpa); | 6857 | defer inst_map.deinit(gpa); |
| 6858 | 6858 | ||
| 6859 | var extra_map: std.AutoHashMapUnmanaged(Zir.ExtraIndex, Zir.ExtraIndex) = .{}; | 6859 | try Module.mapOldZirToNew(gpa, old_zir, file.zir, &inst_map); |
| 6860 | defer extra_map.deinit(gpa); | ||
| 6861 | |||
| 6862 | try Module.mapOldZirToNew(gpa, old_zir, file.zir, &inst_map, &extra_map); | ||
| 6863 | 6860 | ||
| 6864 | var bw = io.bufferedWriter(io.getStdOut().writer()); | 6861 | var bw = io.bufferedWriter(io.getStdOut().writer()); |
| 6865 | const stdout = bw.writer(); | 6862 | const stdout = bw.writer(); |
| ... | @@ -6868,16 +6865,8 @@ pub fn cmdChangelist( | ... | @@ -6868,16 +6865,8 @@ pub fn cmdChangelist( |
| 6868 | var it = inst_map.iterator(); | 6865 | var it = inst_map.iterator(); |
| 6869 | while (it.next()) |entry| { | 6866 | while (it.next()) |entry| { |
| 6870 | try stdout.print(" %{d} => %{d}\n", .{ | 6867 | try stdout.print(" %{d} => %{d}\n", .{ |
| 6871 | entry.key_ptr.*, entry.value_ptr.*, | 6868 | @intFromEnum(entry.key_ptr.*), |
| 6872 | }); | 6869 | @intFromEnum(entry.value_ptr.*), |
| 6873 | } | ||
| 6874 | } | ||
| 6875 | { | ||
| 6876 | try stdout.print("Extra mappings:\n", .{}); | ||
| 6877 | var it = extra_map.iterator(); | ||
| 6878 | while (it.next()) |entry| { | ||
| 6879 | try stdout.print(" {d} => {d}\n", .{ | ||
| 6880 | entry.key_ptr.*, entry.value_ptr.*, | ||
| 6881 | }); | 6870 | }); |
| 6882 | } | 6871 | } |
| 6883 | } | 6872 | } |
src/print_zir.zig+67-122| ... | @@ -521,6 +521,8 @@ const Writer = struct { | ... | @@ -521,6 +521,8 @@ const Writer = struct { |
| 521 | .@"defer" => try self.writeDefer(stream, inst), | 521 | .@"defer" => try self.writeDefer(stream, inst), |
| 522 | .defer_err_code => try self.writeDeferErrCode(stream, inst), | 522 | .defer_err_code => try self.writeDeferErrCode(stream, inst), |
| 523 | 523 | ||
| 524 | .declaration => try self.writeDeclaration(stream, inst), | ||
| 525 | |||
| 524 | .extended => try self.writeExtended(stream, inst), | 526 | .extended => try self.writeExtended(stream, inst), |
| 525 | } | 527 | } |
| 526 | } | 528 | } |
| ... | @@ -1454,8 +1456,9 @@ const Writer = struct { | ... | @@ -1454,8 +1456,9 @@ const Writer = struct { |
| 1454 | 1456 | ||
| 1455 | try stream.writeAll("{\n"); | 1457 | try stream.writeAll("{\n"); |
| 1456 | self.indent += 2; | 1458 | self.indent += 2; |
| 1457 | extra_index = try self.writeDecls(stream, decls_len, extra_index); | 1459 | try self.writeBody(stream, self.code.bodySlice(extra_index, decls_len)); |
| 1458 | self.indent -= 2; | 1460 | self.indent -= 2; |
| 1461 | extra_index += decls_len; | ||
| 1459 | try stream.writeByteNTimes(' ', self.indent); | 1462 | try stream.writeByteNTimes(' ', self.indent); |
| 1460 | try stream.writeAll("}, "); | 1463 | try stream.writeAll("}, "); |
| 1461 | } | 1464 | } |
| ... | @@ -1634,8 +1637,9 @@ const Writer = struct { | ... | @@ -1634,8 +1637,9 @@ const Writer = struct { |
| 1634 | 1637 | ||
| 1635 | try stream.writeAll("{\n"); | 1638 | try stream.writeAll("{\n"); |
| 1636 | self.indent += 2; | 1639 | self.indent += 2; |
| 1637 | extra_index = try self.writeDecls(stream, decls_len, extra_index); | 1640 | try self.writeBody(stream, self.code.bodySlice(extra_index, decls_len)); |
| 1638 | self.indent -= 2; | 1641 | self.indent -= 2; |
| 1642 | extra_index += decls_len; | ||
| 1639 | try stream.writeByteNTimes(' ', self.indent); | 1643 | try stream.writeByteNTimes(' ', self.indent); |
| 1640 | try stream.writeAll("}"); | 1644 | try stream.writeAll("}"); |
| 1641 | } | 1645 | } |
| ... | @@ -1727,124 +1731,6 @@ const Writer = struct { | ... | @@ -1727,124 +1731,6 @@ const Writer = struct { |
| 1727 | try self.writeSrcNode(stream, src_node); | 1731 | try self.writeSrcNode(stream, src_node); |
| 1728 | } | 1732 | } |
| 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 | fn writeEnumDecl(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void { | 1734 | fn writeEnumDecl(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void { |
| 1849 | const small = @as(Zir.Inst.EnumDecl.Small, @bitCast(extended.small)); | 1735 | const small = @as(Zir.Inst.EnumDecl.Small, @bitCast(extended.small)); |
| 1850 | var extra_index: usize = extended.operand; | 1736 | var extra_index: usize = extended.operand; |
| ... | @@ -1891,8 +1777,9 @@ const Writer = struct { | ... | @@ -1891,8 +1777,9 @@ const Writer = struct { |
| 1891 | 1777 | ||
| 1892 | try stream.writeAll("{\n"); | 1778 | try stream.writeAll("{\n"); |
| 1893 | self.indent += 2; | 1779 | self.indent += 2; |
| 1894 | extra_index = try self.writeDecls(stream, decls_len, extra_index); | 1780 | try self.writeBody(stream, self.code.bodySlice(extra_index, decls_len)); |
| 1895 | self.indent -= 2; | 1781 | self.indent -= 2; |
| 1782 | extra_index += decls_len; | ||
| 1896 | try stream.writeByteNTimes(' ', self.indent); | 1783 | try stream.writeByteNTimes(' ', self.indent); |
| 1897 | try stream.writeAll("}, "); | 1784 | try stream.writeAll("}, "); |
| 1898 | } | 1785 | } |
| ... | @@ -1988,7 +1875,7 @@ const Writer = struct { | ... | @@ -1988,7 +1875,7 @@ const Writer = struct { |
| 1988 | 1875 | ||
| 1989 | try stream.writeAll("{\n"); | 1876 | try stream.writeAll("{\n"); |
| 1990 | self.indent += 2; | 1877 | self.indent += 2; |
| 1991 | _ = try self.writeDecls(stream, decls_len, extra_index); | 1878 | try self.writeBody(stream, self.code.bodySlice(extra_index, decls_len)); |
| 1992 | self.indent -= 2; | 1879 | self.indent -= 2; |
| 1993 | try stream.writeByteNTimes(' ', self.indent); | 1880 | try stream.writeByteNTimes(' ', self.indent); |
| 1994 | try stream.writeAll("})"); | 1881 | try stream.writeAll("})"); |
| ... | @@ -2762,6 +2649,64 @@ const Writer = struct { | ... | @@ -2762,6 +2649,64 @@ const Writer = struct { |
| 2762 | try stream.writeByte(')'); | 2649 | try stream.writeByte(')'); |
| 2763 | } | 2650 | } |
| 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 | fn writeInstRef(self: *Writer, stream: anytype, ref: Zir.Inst.Ref) !void { | 2710 | fn writeInstRef(self: *Writer, stream: anytype, ref: Zir.Inst.Ref) !void { |
| 2766 | if (ref == .none) { | 2711 | if (ref == .none) { |
| 2767 | return stream.writeAll(".none"); | 2712 | return stream.writeAll(".none"); |