authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-05-10 21:34:43-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-05-10 21:34:43-07:00
logb9a099e83cf11629554c68c7606836065133f56b
tree4673139264605fba8295c97024035d1dc0fb5cee
parent9e72f317354de029f7e77600901c8cabcaf48c3e

stage2: type declarations ZIR encode AnonNameStrategy

which can be either parent, func, or anon. Here's the enum reproduced in the commit message for convenience: ```zig pub const NameStrategy = enum(u2) { /// Use the same name as the parent declaration name. /// e.g. `const Foo = struct {...};`. parent, /// Use the name of the currently executing comptime function call, /// with the current parameters. e.g. `ArrayList(i32)`. func, /// Create an anonymous name for this declaration. /// Like this: "ParentDeclName_struct_69" anon, }; ``` With this information in the ZIR, a future commit can improve the names of structs, unions, enums, and opaques. In order to accomplish this, the following ZIR instruction forms were removed and replaced with Extended op codes: * struct_decl * struct_decl_packed * struct_decl_extern * union_decl * union_decl_packed * union_decl_extern * enum_decl * enum_decl_nonexhaustive By being extended opcodes, one more u32 is needed, however we more than make up for it by repurposing the 16 "small" bits to provide shorter encodings for when decls_len == 0, fields_len == 0, a source node is not provided, etc. There tends to be no downside, and in fact sometimes upsides, to using an extended op code when there is a need for flag bits, which is the case for all three of these. Likewise, the container layout can be encoded in these bits rather than into the opcode. The following 4 ZIR instructions were added, netting a total of 4 freed up ZIR enum tags for future use: * opaque_decl_anon * opaque_decl_func * error_set_decl_anon * error_set_decl_func This is so that opaques and error sets can have the same name hint as structs, enums, and unions. `std.builtin.ContainerLayout` gets an explicit integer tag type so that it can be used inside packed structs. This commit also makes `Module.Namespace` use a separate set for anonymous decls, thus allowing anonymous decls to share the same `Decl.name` as their owner `Decl` objects.

6 files changed, 809 insertions(+), 390 deletions(-)

BRANCH_TODO+3
......@@ -65,3 +65,6 @@
6565 * use ZIR memory for decl names where possible and also for keys
6666 - this will require more sophisticated changelist detection which does some
6767 pre-emptive deletion of decls from the parent namespace
68
69 * better anonymous Decl naming convention
70 - avoid the global atomic integer for the number because of contention
lib/std/builtin.zig+1-1
......@@ -263,7 +263,7 @@ pub const TypeInfo = union(enum) {
263263
264264 /// This data structure is used by the Zig language code generation and
265265 /// therefore must be kept in sync with the compiler implementation.
266 pub const ContainerLayout = enum {
266 pub const ContainerLayout = enum(u2) {
267267 Auto,
268268 Extern,
269269 Packed,
src/AstGen.zig+236-65
......@@ -85,6 +85,7 @@ pub fn generate(gpa: *Allocator, tree: ast.Tree) InnerError!Zir {
8585 var gen_scope: GenZir = .{
8686 .force_comptime = true,
8787 .parent = null,
88 .anon_name_strategy = .parent,
8889 .decl_node_index = 0,
8990 .decl_line = 0,
9091 .astgen = &astgen,
......@@ -105,7 +106,7 @@ pub fn generate(gpa: *Allocator, tree: ast.Tree) InnerError!Zir {
105106 &gen_scope.base,
106107 0,
107108 container_decl,
108 .struct_decl,
109 .Auto,
109110 )) |struct_decl_ref| {
110111 astgen.extra.items[@enumToInt(Zir.ExtraIndex.main_struct)] = @enumToInt(struct_decl_ref);
111112 } else |err| switch (err) {
......@@ -1959,16 +1960,12 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: ast.Node.Index) Inner
19591960 .union_init_ptr,
19601961 .field_type,
19611962 .field_type_ref,
1962 .struct_decl,
1963 .struct_decl_packed,
1964 .struct_decl_extern,
1965 .union_decl,
1966 .union_decl_packed,
1967 .union_decl_extern,
1968 .enum_decl,
1969 .enum_decl_nonexhaustive,
19701963 .opaque_decl,
1964 .opaque_decl_anon,
1965 .opaque_decl_func,
19711966 .error_set_decl,
1967 .error_set_decl_anon,
1968 .error_set_decl_func,
19721969 .int_to_enum,
19731970 .enum_to_int,
19741971 .type_info,
......@@ -2166,7 +2163,7 @@ fn varDecl(
21662163 const local_val = s.cast(Scope.LocalVal).?;
21672164 if (local_val.name == ident_name) {
21682165 return astgen.failTokNotes(name_token, "redeclaration of '{s}'", .{
2169 @ptrCast([*:0]const u8, astgen.string_bytes.items.ptr) + ident_name,
2166 astgen.nullTerminatedString(ident_name),
21702167 }, &[_]u32{
21712168 try astgen.errNoteTok(
21722169 local_val.token_src,
......@@ -2181,7 +2178,7 @@ fn varDecl(
21812178 const local_ptr = s.cast(Scope.LocalPtr).?;
21822179 if (local_ptr.name == ident_name) {
21832180 return astgen.failTokNotes(name_token, "redeclaration of '{s}'", .{
2184 @ptrCast([*:0]const u8, astgen.string_bytes.items.ptr) + ident_name,
2181 astgen.nullTerminatedString(ident_name),
21852182 }, &[_]u32{
21862183 try astgen.errNoteTok(
21872184 local_ptr.token_src,
......@@ -2941,12 +2938,16 @@ fn globalVarDecl(
29412938 // of the top level declaration.
29422939 const block_inst = try gz.addBlock(.block_inline, node);
29432940
2941 const name_token = var_decl.ast.mut_token + 1;
2942 const name_str_index = try astgen.identAsString(name_token);
2943
29442944 var block_scope: GenZir = .{
29452945 .parent = scope,
29462946 .decl_node_index = node,
29472947 .decl_line = gz.calcLine(node),
29482948 .astgen = astgen,
29492949 .force_comptime = true,
2950 .anon_name_strategy = .parent,
29502951 };
29512952 defer block_scope.instructions.deinit(gpa);
29522953
......@@ -3043,9 +3044,6 @@ fn globalVarDecl(
30433044 _ = try block_scope.addBreak(.break_inline, block_inst, var_inst);
30443045 try block_scope.setBlockBody(block_inst);
30453046
3046 const name_token = var_decl.ast.mut_token + 1;
3047 const name_str_index = try astgen.identAsString(name_token);
3048
30493047 try wip_decls.payload.ensureUnusedCapacity(gpa, 9);
30503048 {
30513049 const contents_hash = std.zig.hashSrc(tree.getNodeSource(node));
......@@ -3258,14 +3256,18 @@ fn structDeclInner(
32583256 scope: *Scope,
32593257 node: ast.Node.Index,
32603258 container_decl: ast.full.ContainerDecl,
3261 tag: Zir.Inst.Tag,
3259 layout: std.builtin.TypeInfo.ContainerLayout,
32623260) InnerError!Zir.Inst.Ref {
32633261 if (container_decl.ast.members.len == 0) {
3264 return gz.addPlNode(tag, node, Zir.Inst.StructDecl{
3262 const decl_inst = try gz.reserveInstructionIndex();
3263 try gz.setStruct(decl_inst, .{
3264 .src_node = node,
3265 .layout = layout,
32653266 .fields_len = 0,
32663267 .body_len = 0,
32673268 .decls_len = 0,
32683269 });
3270 return gz.indexToRef(decl_inst);
32693271 }
32703272
32713273 const astgen = gz.astgen;
......@@ -3437,23 +3439,24 @@ fn structDeclInner(
34373439 }
34383440 }
34393441
3440 const decl_inst = try gz.addBlock(tag, node);
3441 try gz.instructions.append(gpa, decl_inst);
3442 const decl_inst = try gz.reserveInstructionIndex();
34423443 if (block_scope.instructions.items.len != 0) {
34433444 _ = try block_scope.addBreak(.break_inline, decl_inst, .void_value);
34443445 }
34453446
3446 try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.StructDecl).Struct.fields.len +
3447 bit_bag.items.len + @boolToInt(field_index != 0) + fields_data.items.len +
3448 block_scope.instructions.items.len +
3449 wip_decls.bit_bag.items.len + @boolToInt(wip_decls.decl_index != 0) +
3450 wip_decls.payload.items.len);
3451 const zir_datas = astgen.instructions.items(.data);
3452 zir_datas[decl_inst].pl_node.payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.StructDecl{
3447 try gz.setStruct(decl_inst, .{
3448 .src_node = node,
3449 .layout = layout,
34533450 .body_len = @intCast(u32, block_scope.instructions.items.len),
34543451 .fields_len = @intCast(u32, field_index),
34553452 .decls_len = @intCast(u32, wip_decls.decl_index),
34563453 });
3454
3455 try astgen.extra.ensureUnusedCapacity(gpa, bit_bag.items.len +
3456 @boolToInt(field_index != 0) + fields_data.items.len +
3457 block_scope.instructions.items.len +
3458 wip_decls.bit_bag.items.len + @boolToInt(wip_decls.decl_index != 0) +
3459 wip_decls.payload.items.len);
34573460 astgen.extra.appendSliceAssumeCapacity(wip_decls.bit_bag.items); // Likely empty.
34583461 if (wip_decls.decl_index != 0) {
34593462 astgen.extra.appendAssumeCapacity(wip_decls.cur_bit_bag);
......@@ -3476,7 +3479,7 @@ fn unionDeclInner(
34763479 scope: *Scope,
34773480 node: ast.Node.Index,
34783481 members: []const ast.Node.Index,
3479 tag: Zir.Inst.Tag,
3482 layout: std.builtin.TypeInfo.ContainerLayout,
34803483 arg_inst: Zir.Inst.Ref,
34813484 have_auto_enum: bool,
34823485) InnerError!Zir.Inst.Ref {
......@@ -3611,11 +3614,12 @@ fn unionDeclInner(
36113614 const have_type = member.ast.type_expr != 0;
36123615 const have_align = member.ast.align_expr != 0;
36133616 const have_value = member.ast.value_expr != 0;
3617 const unused = false;
36143618 cur_bit_bag = (cur_bit_bag >> bits_per_field) |
36153619 (@as(u32, @boolToInt(have_type)) << 28) |
36163620 (@as(u32, @boolToInt(have_align)) << 29) |
36173621 (@as(u32, @boolToInt(have_value)) << 30) |
3618 (@as(u32, @boolToInt(have_auto_enum)) << 31);
3622 (@as(u32, @boolToInt(unused)) << 31);
36193623
36203624 if (have_type) {
36213625 const field_type = try typeExpr(&block_scope, &block_scope.base, member.ast.type_expr);
......@@ -3662,24 +3666,26 @@ fn unionDeclInner(
36623666 }
36633667 }
36643668
3665 const decl_inst = try gz.addBlock(tag, node);
3666 try gz.instructions.append(gpa, decl_inst);
3669 const decl_inst = try gz.reserveInstructionIndex();
36673670 if (block_scope.instructions.items.len != 0) {
36683671 _ = try block_scope.addBreak(.break_inline, decl_inst, .void_value);
36693672 }
36703673
3671 try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.UnionDecl).Struct.fields.len +
3672 bit_bag.items.len + 1 + fields_data.items.len +
3673 block_scope.instructions.items.len +
3674 wip_decls.bit_bag.items.len + @boolToInt(wip_decls.decl_index != 0) +
3675 wip_decls.payload.items.len);
3676 const zir_datas = astgen.instructions.items(.data);
3677 zir_datas[decl_inst].pl_node.payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.UnionDecl{
3674 try gz.setUnion(decl_inst, .{
3675 .src_node = node,
3676 .layout = layout,
36783677 .tag_type = arg_inst,
36793678 .body_len = @intCast(u32, block_scope.instructions.items.len),
36803679 .fields_len = @intCast(u32, field_index),
36813680 .decls_len = @intCast(u32, wip_decls.decl_index),
3681 .auto_enum_tag = have_auto_enum,
36823682 });
3683
3684 try astgen.extra.ensureUnusedCapacity(gpa, bit_bag.items.len +
3685 1 + fields_data.items.len +
3686 block_scope.instructions.items.len +
3687 wip_decls.bit_bag.items.len + @boolToInt(wip_decls.decl_index != 0) +
3688 wip_decls.payload.items.len);
36833689 astgen.extra.appendSliceAssumeCapacity(wip_decls.bit_bag.items); // Likely empty.
36843690 if (wip_decls.decl_index != 0) {
36853691 astgen.extra.appendAssumeCapacity(wip_decls.cur_bit_bag);
......@@ -3719,29 +3725,27 @@ fn containerDecl(
37193725
37203726 switch (token_tags[container_decl.ast.main_token]) {
37213727 .keyword_struct => {
3722 const tag = if (container_decl.layout_token) |t| switch (token_tags[t]) {
3723 .keyword_packed => Zir.Inst.Tag.struct_decl_packed,
3724 .keyword_extern => Zir.Inst.Tag.struct_decl_extern,
3728 const layout = if (container_decl.layout_token) |t| switch (token_tags[t]) {
3729 .keyword_packed => std.builtin.TypeInfo.ContainerLayout.Packed,
3730 .keyword_extern => std.builtin.TypeInfo.ContainerLayout.Extern,
37253731 else => unreachable,
3726 } else Zir.Inst.Tag.struct_decl;
3732 } else std.builtin.TypeInfo.ContainerLayout.Auto;
37273733
37283734 assert(arg_inst == .none);
37293735
3730 const result = try structDeclInner(gz, scope, node, container_decl, tag);
3736 const result = try structDeclInner(gz, scope, node, container_decl, layout);
37313737 return rvalue(gz, scope, rl, result, node);
37323738 },
37333739 .keyword_union => {
3734 const tag = if (container_decl.layout_token) |t| switch (token_tags[t]) {
3735 .keyword_packed => Zir.Inst.Tag.union_decl_packed,
3736 .keyword_extern => Zir.Inst.Tag.union_decl_extern,
3740 const layout = if (container_decl.layout_token) |t| switch (token_tags[t]) {
3741 .keyword_packed => std.builtin.TypeInfo.ContainerLayout.Packed,
3742 .keyword_extern => std.builtin.TypeInfo.ContainerLayout.Extern,
37373743 else => unreachable,
3738 } else Zir.Inst.Tag.union_decl;
3744 } else std.builtin.TypeInfo.ContainerLayout.Auto;
37393745
3740 // See `Zir.Inst.UnionDecl` doc comments for why this is stored along
3741 // with fields instead of separately.
37423746 const have_auto_enum = container_decl.ast.enum_token != null;
37433747
3744 const result = try unionDeclInner(gz, scope, node, container_decl.ast.members, tag, arg_inst, have_auto_enum);
3748 const result = try unionDeclInner(gz, scope, node, container_decl.ast.members, layout, arg_inst, have_auto_enum);
37453749 return rvalue(gz, scope, rl, result, node);
37463750 },
37473751 .keyword_enum => {
......@@ -3832,10 +3836,7 @@ fn containerDecl(
38323836 }
38333837 // In this case we must generate ZIR code for the tag values, similar to
38343838 // how structs are handled above.
3835 const tag: Zir.Inst.Tag = if (counts.nonexhaustive_node == 0)
3836 .enum_decl
3837 else
3838 .enum_decl_nonexhaustive;
3839 const nonexhaustive = counts.nonexhaustive_node != 0;
38393840
38403841 // The enum_decl instruction introduces a scope in which the decls of the enum
38413842 // are in scope, so that tag values can refer to decls within the enum itself.
......@@ -3995,24 +3996,25 @@ fn containerDecl(
39953996 }
39963997 }
39973998
3998 const decl_inst = try gz.addBlock(tag, node);
3999 try gz.instructions.append(gpa, decl_inst);
3999 const decl_inst = try gz.reserveInstructionIndex();
40004000 if (block_scope.instructions.items.len != 0) {
40014001 _ = try block_scope.addBreak(.break_inline, decl_inst, .void_value);
40024002 }
40034003
4004 try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.EnumDecl).Struct.fields.len +
4005 bit_bag.items.len + 1 + fields_data.items.len +
4006 block_scope.instructions.items.len +
4007 wip_decls.bit_bag.items.len + @boolToInt(wip_decls.decl_index != 0) +
4008 wip_decls.payload.items.len);
4009 const zir_datas = astgen.instructions.items(.data);
4010 zir_datas[decl_inst].pl_node.payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.EnumDecl{
4004 try gz.setEnum(decl_inst, .{
4005 .src_node = node,
4006 .nonexhaustive = nonexhaustive,
40114007 .tag_type = arg_inst,
40124008 .body_len = @intCast(u32, block_scope.instructions.items.len),
40134009 .fields_len = @intCast(u32, field_index),
40144010 .decls_len = @intCast(u32, wip_decls.decl_index),
40154011 });
4012
4013 try astgen.extra.ensureUnusedCapacity(gpa, bit_bag.items.len +
4014 1 + fields_data.items.len +
4015 block_scope.instructions.items.len +
4016 wip_decls.bit_bag.items.len + @boolToInt(wip_decls.decl_index != 0) +
4017 wip_decls.payload.items.len);
40164018 astgen.extra.appendSliceAssumeCapacity(wip_decls.bit_bag.items); // Likely empty.
40174019 if (wip_decls.decl_index != 0) {
40184020 astgen.extra.appendAssumeCapacity(wip_decls.cur_bit_bag);
......@@ -4118,7 +4120,12 @@ fn containerDecl(
41184120 wip_decls.cur_bit_bag >>= @intCast(u5, empty_slot_count * WipDecls.bits_per_field);
41194121 }
41204122 }
4121 const decl_inst = try gz.addBlock(.opaque_decl, node);
4123 const tag: Zir.Inst.Tag = switch (gz.anon_name_strategy) {
4124 .parent => .opaque_decl,
4125 .anon => .opaque_decl_anon,
4126 .func => .opaque_decl_func,
4127 };
4128 const decl_inst = try gz.addBlock(tag, node);
41224129 try gz.instructions.append(gpa, decl_inst);
41234130
41244131 try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.OpaqueDecl).Struct.fields.len +
......@@ -4173,6 +4180,11 @@ fn errorSetDecl(
41734180 }
41744181 }
41754182
4183 const tag: Zir.Inst.Tag = switch (gz.anon_name_strategy) {
4184 .parent => .error_set_decl,
4185 .anon => .error_set_decl_anon,
4186 .func => .error_set_decl_func,
4187 };
41764188 const result = try gz.addPlNode(.error_set_decl, node, Zir.Inst.ErrorSetDecl{
41774189 .fields_len = @intCast(u32, field_names.items.len),
41784190 });
......@@ -5907,7 +5919,6 @@ fn charLiteral(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index)
59075919 const value = std.zig.parseCharLiteral(slice, &bad_index) catch |err| switch (err) {
59085920 error.InvalidCharacter => {
59095921 const bad_byte = slice[bad_index];
5910 const token_starts = tree.tokens.items(.start);
59115922 return astgen.failOff(
59125923 main_token,
59135924 @intCast(u32, bad_index),
......@@ -7779,6 +7790,8 @@ const GenZir = struct {
77797790 const base_tag: Scope.Tag = .gen_zir;
77807791 base: Scope = Scope{ .tag = base_tag },
77817792 force_comptime: bool,
7793 /// How decls created in this scope should be named.
7794 anon_name_strategy: Zir.Inst.NameStrategy = .anon,
77827795 /// The end of special indexes. `Zir.Inst.Ref` subtracts against this number to convert
77837796 /// to `Zir.Inst.Index`. The default here is correct if there are 0 parameters.
77847797 ref_start_index: u32 = Zir.Inst.Ref.typed_value_map.len,
......@@ -8623,18 +8636,176 @@ const GenZir = struct {
86238636 return new_index;
86248637 }
86258638
8639 fn setStruct(gz: *GenZir, inst: Zir.Inst.Index, args: struct {
8640 src_node: ast.Node.Index,
8641 body_len: u32,
8642 fields_len: u32,
8643 decls_len: u32,
8644 layout: std.builtin.TypeInfo.ContainerLayout,
8645 }) !void {
8646 const astgen = gz.astgen;
8647 const gpa = astgen.gpa;
8648
8649 try astgen.extra.ensureUnusedCapacity(gpa, 4);
8650 const payload_index = @intCast(u32, astgen.extra.items.len);
8651
8652 if (args.src_node != 0) {
8653 const node_offset = gz.nodeIndexToRelative(args.src_node);
8654 astgen.extra.appendAssumeCapacity(@bitCast(u32, node_offset));
8655 }
8656 if (args.body_len != 0) {
8657 astgen.extra.appendAssumeCapacity(args.body_len);
8658 }
8659 if (args.fields_len != 0) {
8660 astgen.extra.appendAssumeCapacity(args.fields_len);
8661 }
8662 if (args.decls_len != 0) {
8663 astgen.extra.appendAssumeCapacity(args.decls_len);
8664 }
8665 astgen.instructions.set(inst, .{
8666 .tag = .extended,
8667 .data = .{ .extended = .{
8668 .opcode = .struct_decl,
8669 .small = @bitCast(u16, Zir.Inst.StructDecl.Small{
8670 .has_src_node = args.src_node != 0,
8671 .has_body_len = args.body_len != 0,
8672 .has_fields_len = args.fields_len != 0,
8673 .has_decls_len = args.decls_len != 0,
8674 .name_strategy = gz.anon_name_strategy,
8675 .layout = args.layout,
8676 }),
8677 .operand = payload_index,
8678 } },
8679 });
8680 }
8681
8682 fn setUnion(gz: *GenZir, inst: Zir.Inst.Index, args: struct {
8683 src_node: ast.Node.Index,
8684 tag_type: Zir.Inst.Ref,
8685 body_len: u32,
8686 fields_len: u32,
8687 decls_len: u32,
8688 layout: std.builtin.TypeInfo.ContainerLayout,
8689 auto_enum_tag: bool,
8690 }) !void {
8691 const astgen = gz.astgen;
8692 const gpa = astgen.gpa;
8693
8694 try astgen.extra.ensureUnusedCapacity(gpa, 5);
8695 const payload_index = @intCast(u32, astgen.extra.items.len);
8696
8697 if (args.src_node != 0) {
8698 const node_offset = gz.nodeIndexToRelative(args.src_node);
8699 astgen.extra.appendAssumeCapacity(@bitCast(u32, node_offset));
8700 }
8701 if (args.tag_type != .none) {
8702 astgen.extra.appendAssumeCapacity(@enumToInt(args.tag_type));
8703 }
8704 if (args.body_len != 0) {
8705 astgen.extra.appendAssumeCapacity(args.body_len);
8706 }
8707 if (args.fields_len != 0) {
8708 astgen.extra.appendAssumeCapacity(args.fields_len);
8709 }
8710 if (args.decls_len != 0) {
8711 astgen.extra.appendAssumeCapacity(args.decls_len);
8712 }
8713 astgen.instructions.set(inst, .{
8714 .tag = .extended,
8715 .data = .{ .extended = .{
8716 .opcode = .union_decl,
8717 .small = @bitCast(u16, Zir.Inst.UnionDecl.Small{
8718 .has_src_node = args.src_node != 0,
8719 .has_tag_type = args.tag_type != .none,
8720 .has_body_len = args.body_len != 0,
8721 .has_fields_len = args.fields_len != 0,
8722 .has_decls_len = args.decls_len != 0,
8723 .name_strategy = gz.anon_name_strategy,
8724 .layout = args.layout,
8725 .auto_enum_tag = args.auto_enum_tag,
8726 }),
8727 .operand = payload_index,
8728 } },
8729 });
8730 }
8731
8732 fn setEnum(gz: *GenZir, inst: Zir.Inst.Index, args: struct {
8733 src_node: ast.Node.Index,
8734 tag_type: Zir.Inst.Ref,
8735 body_len: u32,
8736 fields_len: u32,
8737 decls_len: u32,
8738 nonexhaustive: bool,
8739 }) !void {
8740 const astgen = gz.astgen;
8741 const gpa = astgen.gpa;
8742
8743 try astgen.extra.ensureUnusedCapacity(gpa, 5);
8744 const payload_index = @intCast(u32, astgen.extra.items.len);
8745
8746 if (args.src_node != 0) {
8747 const node_offset = gz.nodeIndexToRelative(args.src_node);
8748 astgen.extra.appendAssumeCapacity(@bitCast(u32, node_offset));
8749 }
8750 if (args.tag_type != .none) {
8751 astgen.extra.appendAssumeCapacity(@enumToInt(args.tag_type));
8752 }
8753 if (args.body_len != 0) {
8754 astgen.extra.appendAssumeCapacity(args.body_len);
8755 }
8756 if (args.fields_len != 0) {
8757 astgen.extra.appendAssumeCapacity(args.fields_len);
8758 }
8759 if (args.decls_len != 0) {
8760 astgen.extra.appendAssumeCapacity(args.decls_len);
8761 }
8762 astgen.instructions.set(inst, .{
8763 .tag = .extended,
8764 .data = .{ .extended = .{
8765 .opcode = .enum_decl,
8766 .small = @bitCast(u16, Zir.Inst.EnumDecl.Small{
8767 .has_src_node = args.src_node != 0,
8768 .has_tag_type = args.tag_type != .none,
8769 .has_body_len = args.body_len != 0,
8770 .has_fields_len = args.fields_len != 0,
8771 .has_decls_len = args.decls_len != 0,
8772 .name_strategy = gz.anon_name_strategy,
8773 .nonexhaustive = args.nonexhaustive,
8774 }),
8775 .operand = payload_index,
8776 } },
8777 });
8778 }
8779
86268780 fn add(gz: *GenZir, inst: Zir.Inst) !Zir.Inst.Ref {
86278781 return gz.indexToRef(try gz.addAsIndex(inst));
86288782 }
86298783
86308784 fn addAsIndex(gz: *GenZir, inst: Zir.Inst) !Zir.Inst.Index {
86318785 const gpa = gz.astgen.gpa;
8632 try gz.instructions.ensureCapacity(gpa, gz.instructions.items.len + 1);
8633 try gz.astgen.instructions.ensureCapacity(gpa, gz.astgen.instructions.len + 1);
8786 try gz.instructions.ensureUnusedCapacity(gpa, 1);
8787 try gz.astgen.instructions.ensureUnusedCapacity(gpa, 1);
86348788
86358789 const new_index = @intCast(Zir.Inst.Index, gz.astgen.instructions.len);
86368790 gz.astgen.instructions.appendAssumeCapacity(inst);
86378791 gz.instructions.appendAssumeCapacity(new_index);
86388792 return new_index;
86398793 }
8794
8795 fn reserveInstructionIndex(gz: *GenZir) !Zir.Inst.Index {
8796 const gpa = gz.astgen.gpa;
8797 try gz.instructions.ensureUnusedCapacity(gpa, 1);
8798 try gz.astgen.instructions.ensureUnusedCapacity(gpa, 1);
8799
8800 const new_index = @intCast(Zir.Inst.Index, gz.astgen.instructions.len);
8801 gz.astgen.instructions.len += 1;
8802 gz.instructions.appendAssumeCapacity(new_index);
8803 return new_index;
8804 }
86408805};
8806
8807/// This can only be for short-lived references; the memory becomes invalidated
8808/// when another string is added.
8809fn nullTerminatedString(astgen: AstGen, index: usize) [*:0]const u8 {
8810 return @ptrCast([*:0]const u8, astgen.string_bytes.items.ptr) + index;
8811}
src/Module.zig+102-49
......@@ -75,6 +75,8 @@ failed_files: std.AutoArrayHashMapUnmanaged(*Scope.File, ?*ErrorMsg) = .{},
7575/// The ErrorMsg memory is owned by the `Export`, using Module's general purpose allocator.
7676failed_exports: std.AutoArrayHashMapUnmanaged(*Export, *ErrorMsg) = .{},
7777
78next_anon_name_index: usize = 0,
79
7880/// Candidates for deletion. After a semantic analysis update completes, this list
7981/// contains Decls that need to be deleted if they end up having no references to them.
8082deletion_set: std.AutoArrayHashMapUnmanaged(*Decl, void) = .{},
......@@ -884,8 +886,11 @@ pub const Scope = struct {
884886 /// Declaration order is preserved via entry order.
885887 /// Key memory is owned by `decl.name`.
886888 /// TODO save memory with https://github.com/ziglang/zig/issues/8619.
889 /// Anonymous decls are not stored here; they are kept in `anon_decls` instead.
887890 decls: std.StringArrayHashMapUnmanaged(*Decl) = .{},
888891
892 anon_decls: std.AutoArrayHashMapUnmanaged(*Decl, void) = .{},
893
889894 pub fn deinit(ns: *Namespace, mod: *Module) void {
890895 ns.clearDecls(mod);
891896 ns.* = undefined;
......@@ -899,15 +904,27 @@ pub const Scope = struct {
899904 var decls = ns.decls;
900905 ns.decls = .{};
901906
907 var anon_decls = ns.anon_decls;
908 ns.anon_decls = .{};
909
902910 for (decls.items()) |entry| {
903911 entry.value.destroy(mod);
904912 }
905913 decls.deinit(gpa);
914
915 for (anon_decls.items()) |entry| {
916 entry.key.destroy(mod);
917 }
918 anon_decls.deinit(gpa);
906919 }
907920
908921 pub fn removeDecl(ns: *Namespace, child: *Decl) void {
909 // Preserve declaration order.
910 _ = ns.decls.orderedRemove(mem.spanZ(child.name));
922 if (child.zir_decl_index == 0) {
923 _ = ns.anon_decls.swapRemove(child);
924 } else {
925 // Preserve declaration order.
926 _ = ns.decls.orderedRemove(mem.spanZ(child.name));
927 }
911928 }
912929
913930 // This renders e.g. "std.fs.Dir.OpenOptions"
......@@ -2607,10 +2624,14 @@ fn updateZirRefs(gpa: *Allocator, file: *Scope.File, old_zir: Zir) !void {
26072624 }
26082625
26092626 if (decl.getInnerNamespace()) |namespace| {
2610 for (namespace.decls.items()) |*entry| {
2627 for (namespace.decls.items()) |entry| {
26112628 const sub_decl = entry.value;
26122629 try decl_stack.append(gpa, sub_decl);
26132630 }
2631 for (namespace.anon_decls.items()) |entry| {
2632 const sub_decl = entry.key;
2633 try decl_stack.append(gpa, sub_decl);
2634 }
26142635 }
26152636 }
26162637}
......@@ -3741,31 +3762,17 @@ pub fn constIntBig(mod: *Module, arena: *Allocator, src: LazySrcLoc, ty: Type, b
37413762pub fn createAnonymousDecl(mod: *Module, scope: *Scope, typed_value: TypedValue) !*Decl {
37423763 const scope_decl = scope.ownerDecl().?;
37433764 const namespace = scope_decl.namespace;
3744 try namespace.decls.ensureUnusedCapacity(mod.gpa, 1);
3745
3746 // Find a unique name for the anon decl.
3747 var name_buf = std.ArrayList(u8).init(mod.gpa);
3748 defer name_buf.deinit();
3749
3750 try name_buf.appendSlice(mem.spanZ(scope_decl.name));
3751 var name_index: usize = namespace.decls.count();
3752
3753 const new_decl = while (true) {
3754 const gop = namespace.decls.getOrPutAssumeCapacity(name_buf.items);
3755 if (!gop.found_existing) {
3756 const name = try name_buf.toOwnedSliceSentinel(0);
3757 const new_decl = try mod.allocateNewDecl(namespace, scope_decl.src_node);
3758 new_decl.name = name;
3759 gop.entry.key = name;
3760 gop.entry.value = new_decl;
3761 break gop.entry.value;
3762 }
3765 try namespace.anon_decls.ensureUnusedCapacity(mod.gpa, 1);
3766
3767 const name_index = mod.getNextAnonNameIndex();
3768 const name = try std.fmt.allocPrintZ(mod.gpa, "{s}__anon_{d}", .{
3769 scope_decl.name, name_index,
3770 });
3771 errdefer mod.gpa.free(name);
37633772
3764 name_buf.clearRetainingCapacity();
3765 try name_buf.writer().print("{s}__anon_{d}", .{ scope_decl.name, name_index });
3766 name_index += 1;
3767 } else unreachable; // TODO should not need else unreachable on while(true)
3773 const new_decl = try mod.allocateNewDecl(namespace, scope_decl.src_node);
37683774
3775 new_decl.name = name;
37693776 new_decl.src_line = scope_decl.src_line;
37703777 new_decl.ty = typed_value.ty;
37713778 new_decl.val = typed_value.val;
......@@ -3773,6 +3780,8 @@ pub fn createAnonymousDecl(mod: *Module, scope: *Scope, typed_value: TypedValue)
37733780 new_decl.analysis = .complete;
37743781 new_decl.generation = mod.generation;
37753782
3783 namespace.anon_decls.putAssumeCapacityNoClobber(new_decl, {});
3784
37763785 // TODO: This generates the Decl into the machine code file if it is of a
37773786 // type that is non-zero size. We should be able to further improve the
37783787 // compiler to omit Decls which are only referenced at compile-time and not runtime.
......@@ -3784,6 +3793,10 @@ pub fn createAnonymousDecl(mod: *Module, scope: *Scope, typed_value: TypedValue)
37843793 return new_decl;
37853794}
37863795
3796fn getNextAnonNameIndex(mod: *Module) usize {
3797 return @atomicRmw(usize, &mod.next_anon_name_index, .Add, 1, .Monotonic);
3798}
3799
37873800/// This looks up a bare identifier in the given scope. This will walk up the tree of namespaces
37883801/// in scope and check each one for the identifier.
37893802/// TODO emit a compile error if more than one decl would be matched.
......@@ -4394,18 +4407,38 @@ pub fn analyzeStructFields(mod: *Module, struct_obj: *Struct) InnerError!void {
43944407
43954408 const gpa = mod.gpa;
43964409 const zir = struct_obj.owner_decl.namespace.file_scope.zir;
4397 const inst_data = zir.instructions.items(.data)[struct_obj.zir_index].pl_node;
4398 const src = inst_data.src();
4399 const extra = zir.extraData(Zir.Inst.StructDecl, inst_data.payload_index);
4400 const fields_len = extra.data.fields_len;
4401 const decls_len = extra.data.decls_len;
4410 const extended = zir.instructions.items(.data)[struct_obj.zir_index].extended;
4411 assert(extended.opcode == .struct_decl);
4412 const small = @bitCast(Zir.Inst.StructDecl.Small, extended.small);
4413 var extra_index: usize = extended.operand;
4414
4415 const src: LazySrcLoc = .{ .node_offset = struct_obj.node_offset };
4416 extra_index += @boolToInt(small.has_src_node);
4417
4418 const body_len = if (small.has_body_len) blk: {
4419 const body_len = zir.extra[extra_index];
4420 extra_index += 1;
4421 break :blk body_len;
4422 } else 0;
4423
4424 const fields_len = if (small.has_fields_len) blk: {
4425 const fields_len = zir.extra[extra_index];
4426 extra_index += 1;
4427 break :blk fields_len;
4428 } else 0;
4429
4430 const decls_len = if (small.has_decls_len) decls_len: {
4431 const decls_len = zir.extra[extra_index];
4432 extra_index += 1;
4433 break :decls_len decls_len;
4434 } else 0;
44024435
44034436 // Skip over decls.
4404 var decls_it = zir.declIterator(struct_obj.zir_index);
4437 var decls_it = zir.declIteratorInner(extra_index, decls_len);
44054438 while (decls_it.next()) |_| {}
4406 var extra_index = decls_it.extra_index;
4439 extra_index = decls_it.extra_index;
44074440
4408 const body = zir.extra[extra_index..][0..extra.data.body_len];
4441 const body = zir.extra[extra_index..][0..body_len];
44094442 if (fields_len == 0) {
44104443 assert(body.len == 0);
44114444 return;
......@@ -4525,18 +4558,44 @@ pub fn analyzeUnionFields(mod: *Module, union_obj: *Union) InnerError!void {
45254558
45264559 const gpa = mod.gpa;
45274560 const zir = union_obj.owner_decl.namespace.file_scope.zir;
4528 const inst_data = zir.instructions.items(.data)[union_obj.zir_index].pl_node;
4529 const src = inst_data.src();
4530 const extra = zir.extraData(Zir.Inst.UnionDecl, inst_data.payload_index);
4531 const fields_len = extra.data.fields_len;
4532 const decls_len = extra.data.decls_len;
4561 const extended = zir.instructions.items(.data)[union_obj.zir_index].extended;
4562 assert(extended.opcode == .union_decl);
4563 const small = @bitCast(Zir.Inst.UnionDecl.Small, extended.small);
4564 var extra_index: usize = extended.operand;
4565
4566 const src: LazySrcLoc = .{ .node_offset = union_obj.node_offset };
4567 extra_index += @boolToInt(small.has_src_node);
4568
4569 const tag_type_ref = if (small.has_tag_type) blk: {
4570 const tag_type_ref = @intToEnum(Zir.Inst.Ref, zir.extra[extra_index]);
4571 extra_index += 1;
4572 break :blk tag_type_ref;
4573 } else .none;
4574
4575 const body_len = if (small.has_body_len) blk: {
4576 const body_len = zir.extra[extra_index];
4577 extra_index += 1;
4578 break :blk body_len;
4579 } else 0;
4580
4581 const fields_len = if (small.has_fields_len) blk: {
4582 const fields_len = zir.extra[extra_index];
4583 extra_index += 1;
4584 break :blk fields_len;
4585 } else 0;
4586
4587 const decls_len = if (small.has_decls_len) decls_len: {
4588 const decls_len = zir.extra[extra_index];
4589 extra_index += 1;
4590 break :decls_len decls_len;
4591 } else 0;
45334592
45344593 // Skip over decls.
4535 var decls_it = zir.declIterator(union_obj.zir_index);
4594 var decls_it = zir.declIteratorInner(extra_index, decls_len);
45364595 while (decls_it.next()) |_| {}
4537 var extra_index = decls_it.extra_index;
4596 extra_index = decls_it.extra_index;
45384597
4539 const body = zir.extra[extra_index..][0..extra.data.body_len];
4598 const body = zir.extra[extra_index..][0..body_len];
45404599 if (fields_len == 0) {
45414600 assert(body.len == 0);
45424601 return;
......@@ -4580,8 +4639,6 @@ pub fn analyzeUnionFields(mod: *Module, union_obj: *Union) InnerError!void {
45804639 _ = try sema.analyzeBody(&block, body);
45814640 }
45824641
4583 var auto_enum_tag: ?bool = null;
4584
45854642 const bits_per_field = 4;
45864643 const fields_per_u32 = 32 / bits_per_field;
45874644 const bit_bags_count = std.math.divCeil(usize, fields_len, fields_per_u32) catch unreachable;
......@@ -4603,10 +4660,6 @@ pub fn analyzeUnionFields(mod: *Module, union_obj: *Union) InnerError!void {
46034660 const unused = @truncate(u1, cur_bit_bag) != 0;
46044661 cur_bit_bag >>= 1;
46054662
4606 if (auto_enum_tag == null) {
4607 auto_enum_tag = unused;
4608 }
4609
46104663 const field_name_zir = zir.nullTerminatedString(zir.extra[extra_index]);
46114664 extra_index += 1;
46124665
......@@ -4653,7 +4706,7 @@ pub fn analyzeUnionFields(mod: *Module, union_obj: *Union) InnerError!void {
46534706 }
46544707 }
46554708
4656 // TODO resolve the union tag type
4709 // TODO resolve the union tag_type_ref
46574710}
46584711
46594712/// Called from `performAllTheWork`, after all AstGen workers have finished,
src/Sema.zig+104-47
......@@ -350,16 +350,12 @@ pub fn analyzeBody(
350350 .trunc => try sema.zirUnaryMath(block, inst),
351351 .round => try sema.zirUnaryMath(block, inst),
352352
353 .struct_decl => try sema.zirStructDecl(block, inst, .Auto),
354 .struct_decl_packed => try sema.zirStructDecl(block, inst, .Packed),
355 .struct_decl_extern => try sema.zirStructDecl(block, inst, .Extern),
356 .enum_decl => try sema.zirEnumDecl(block, inst, false),
357 .enum_decl_nonexhaustive => try sema.zirEnumDecl(block, inst, true),
358 .union_decl => try sema.zirUnionDecl(block, inst, .Auto),
359 .union_decl_packed => try sema.zirUnionDecl(block, inst, .Packed),
360 .union_decl_extern => try sema.zirUnionDecl(block, inst, .Extern),
361 .opaque_decl => try sema.zirOpaqueDecl(block, inst),
362 .error_set_decl => try sema.zirErrorSetDecl(block, inst),
353 .opaque_decl => try sema.zirOpaqueDecl(block, inst, .parent),
354 .opaque_decl_anon => try sema.zirOpaqueDecl(block, inst, .anon),
355 .opaque_decl_func => try sema.zirOpaqueDecl(block, inst, .func),
356 .error_set_decl => try sema.zirErrorSetDecl(block, inst, .parent),
357 .error_set_decl_anon => try sema.zirErrorSetDecl(block, inst, .anon),
358 .error_set_decl_func => try sema.zirErrorSetDecl(block, inst, .func),
363359
364360 .add => try sema.zirArithmetic(block, inst),
365361 .addwrap => try sema.zirArithmetic(block, inst),
......@@ -515,6 +511,9 @@ fn zirExtended(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerErro
515511 // zig fmt: off
516512 .func => return sema.zirFuncExtended( block, extended, inst),
517513 .variable => return sema.zirVarExtended( block, extended),
514 .struct_decl => return sema.zirStructDecl( block, extended, inst),
515 .enum_decl => return sema.zirEnumDecl( block, extended),
516 .union_decl => return sema.zirUnionDecl( block, extended, inst),
518517 .ret_ptr => return sema.zirRetPtr( block, extended),
519518 .ret_type => return sema.zirRetType( block, extended),
520519 .this => return sema.zirThis( block, extended),
......@@ -686,21 +685,34 @@ pub fn analyzeStructDecl(
686685 inst: Zir.Inst.Index,
687686 struct_obj: *Module.Struct,
688687) InnerError!void {
689 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
690 const extra = sema.code.extraData(Zir.Inst.StructDecl, inst_data.payload_index);
691 const decls_len = extra.data.decls_len;
688 const extended = sema.code.instructions.items(.data)[inst].extended;
689 assert(extended.opcode == .struct_decl);
690 const small = @bitCast(Zir.Inst.StructDecl.Small, extended.small);
691
692 var extra_index: usize = extended.operand;
693 extra_index += @boolToInt(small.has_src_node);
694 extra_index += @boolToInt(small.has_body_len);
695 extra_index += @boolToInt(small.has_fields_len);
696 const decls_len = if (small.has_decls_len) blk: {
697 const decls_len = sema.code.extra[extra_index];
698 extra_index += 1;
699 break :blk decls_len;
700 } else 0;
692701
693 _ = try sema.mod.scanNamespace(&struct_obj.namespace, extra.end, decls_len, new_decl);
702 _ = try sema.mod.scanNamespace(&struct_obj.namespace, extra_index, decls_len, new_decl);
694703}
695704
696705fn zirStructDecl(
697706 sema: *Sema,
698707 block: *Scope.Block,
708 extended: Zir.Inst.Extended.InstData,
699709 inst: Zir.Inst.Index,
700 layout: std.builtin.TypeInfo.ContainerLayout,
701710) InnerError!*Inst {
702 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
703 const src = inst_data.src();
711 const small = @bitCast(Zir.Inst.StructDecl.Small, extended.small);
712 const src: LazySrcLoc = if (small.has_src_node) blk: {
713 const node_offset = @bitCast(i32, sema.code.extra[extended.operand]);
714 break :blk .{ .node_offset = node_offset };
715 } else sema.src;
704716
705717 var new_decl_arena = std.heap.ArenaAllocator.init(sema.gpa);
706718
......@@ -714,9 +726,9 @@ fn zirStructDecl(
714726 struct_obj.* = .{
715727 .owner_decl = new_decl,
716728 .fields = .{},
717 .node_offset = inst_data.src_node,
729 .node_offset = src.node_offset,
718730 .zir_index = inst,
719 .layout = layout,
731 .layout = small.layout,
720732 .status = .none,
721733 .namespace = .{
722734 .parent = sema.owner_decl.namespace,
......@@ -735,27 +747,53 @@ fn zirStructDecl(
735747fn zirEnumDecl(
736748 sema: *Sema,
737749 block: *Scope.Block,
738 inst: Zir.Inst.Index,
739 nonexhaustive: bool,
750 extended: Zir.Inst.Extended.InstData,
740751) InnerError!*Inst {
741752 const tracy = trace(@src());
742753 defer tracy.end();
743754
744755 const gpa = sema.gpa;
745 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
746 const src = inst_data.src();
747 const extra = sema.code.extraData(Zir.Inst.EnumDecl, inst_data.payload_index);
748 const fields_len = extra.data.fields_len;
749 const decls_len = extra.data.decls_len;
756 const small = @bitCast(Zir.Inst.EnumDecl.Small, extended.small);
757 var extra_index: usize = extended.operand;
758
759 const src: LazySrcLoc = if (small.has_src_node) blk: {
760 const node_offset = @bitCast(i32, sema.code.extra[extra_index]);
761 extra_index += 1;
762 break :blk .{ .node_offset = node_offset };
763 } else sema.src;
764
765 const tag_type_ref = if (small.has_tag_type) blk: {
766 const tag_type_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
767 extra_index += 1;
768 break :blk tag_type_ref;
769 } else .none;
770
771 const body_len = if (small.has_body_len) blk: {
772 const body_len = sema.code.extra[extra_index];
773 extra_index += 1;
774 break :blk body_len;
775 } else 0;
776
777 const fields_len = if (small.has_fields_len) blk: {
778 const fields_len = sema.code.extra[extra_index];
779 extra_index += 1;
780 break :blk fields_len;
781 } else 0;
782
783 const decls_len = if (small.has_decls_len) blk: {
784 const decls_len = sema.code.extra[extra_index];
785 extra_index += 1;
786 break :blk decls_len;
787 } else 0;
750788
751789 var new_decl_arena = std.heap.ArenaAllocator.init(gpa);
752790
753791 const tag_ty = blk: {
754 if (extra.data.tag_type != .none) {
792 if (tag_type_ref != .none) {
755793 // TODO better source location
756794 // TODO (needs AstGen fix too) move this eval to the block so it gets allocated
757795 // in the new decl arena.
758 break :blk try sema.resolveType(block, src, extra.data.tag_type);
796 break :blk try sema.resolveType(block, src, tag_type_ref);
759797 }
760798 const bits = std.math.log2_int_ceil(usize, fields_len);
761799 break :blk try Type.Tag.int_unsigned.create(&new_decl_arena.allocator, bits);
......@@ -764,7 +802,7 @@ fn zirEnumDecl(
764802 const enum_obj = try new_decl_arena.allocator.create(Module.EnumFull);
765803 const enum_ty_payload = try new_decl_arena.allocator.create(Type.Payload.EnumFull);
766804 enum_ty_payload.* = .{
767 .base = .{ .tag = if (nonexhaustive) .enum_nonexhaustive else .enum_full },
805 .base = .{ .tag = if (small.nonexhaustive) .enum_nonexhaustive else .enum_full },
768806 .data = enum_obj,
769807 };
770808 const enum_ty = Type.initPayload(&enum_ty_payload.base);
......@@ -778,7 +816,7 @@ fn zirEnumDecl(
778816 .tag_ty = tag_ty,
779817 .fields = .{},
780818 .values = .{},
781 .node_offset = inst_data.src_node,
819 .node_offset = src.node_offset,
782820 .namespace = .{
783821 .parent = sema.owner_decl.namespace,
784822 .ty = enum_ty,
......@@ -789,14 +827,9 @@ fn zirEnumDecl(
789827 &enum_obj.namespace, new_decl, new_decl.name,
790828 });
791829
792 var extra_index: usize = try sema.mod.scanNamespace(
793 &enum_obj.namespace,
794 extra.end,
795 decls_len,
796 new_decl,
797 );
830 extra_index = try sema.mod.scanNamespace(&enum_obj.namespace, extra_index, decls_len, new_decl);
798831
799 const body = sema.code.extra[extra_index..][0..extra.data.body_len];
832 const body = sema.code.extra[extra_index..][0..body_len];
800833 if (fields_len == 0) {
801834 assert(body.len == 0);
802835 try new_decl.finalizeNewArena(&new_decl_arena);
......@@ -894,16 +927,30 @@ fn zirEnumDecl(
894927fn zirUnionDecl(
895928 sema: *Sema,
896929 block: *Scope.Block,
930 extended: Zir.Inst.Extended.InstData,
897931 inst: Zir.Inst.Index,
898 layout: std.builtin.TypeInfo.ContainerLayout,
899932) InnerError!*Inst {
900933 const tracy = trace(@src());
901934 defer tracy.end();
902935
903 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
904 const src = inst_data.src();
905 const extra = sema.code.extraData(Zir.Inst.UnionDecl, inst_data.payload_index);
906 const decls_len = extra.data.decls_len;
936 const small = @bitCast(Zir.Inst.UnionDecl.Small, extended.small);
937 var extra_index: usize = extended.operand;
938
939 const src: LazySrcLoc = if (small.has_src_node) blk: {
940 const node_offset = @bitCast(i32, sema.code.extra[extra_index]);
941 extra_index += 1;
942 break :blk .{ .node_offset = node_offset };
943 } else sema.src;
944
945 extra_index += @boolToInt(small.has_tag_type);
946 extra_index += @boolToInt(small.has_body_len);
947 extra_index += @boolToInt(small.has_fields_len);
948
949 const decls_len = if (small.has_decls_len) blk: {
950 const decls_len = sema.code.extra[extra_index];
951 extra_index += 1;
952 break :blk decls_len;
953 } else 0;
907954
908955 var new_decl_arena = std.heap.ArenaAllocator.init(sema.gpa);
909956
......@@ -918,9 +965,9 @@ fn zirUnionDecl(
918965 .owner_decl = new_decl,
919966 .tag_ty = Type.initTag(.@"null"),
920967 .fields = .{},
921 .node_offset = inst_data.src_node,
968 .node_offset = src.node_offset,
922969 .zir_index = inst,
923 .layout = layout,
970 .layout = small.layout,
924971 .status = .none,
925972 .namespace = .{
926973 .parent = sema.owner_decl.namespace,
......@@ -932,13 +979,18 @@ fn zirUnionDecl(
932979 &union_obj.namespace, new_decl, new_decl.name,
933980 });
934981
935 _ = try sema.mod.scanNamespace(&union_obj.namespace, extra.end, decls_len, new_decl);
982 _ = try sema.mod.scanNamespace(&union_obj.namespace, extra_index, decls_len, new_decl);
936983
937984 try new_decl.finalizeNewArena(&new_decl_arena);
938985 return sema.analyzeDeclVal(block, src, new_decl);
939986}
940987
941fn zirOpaqueDecl(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
988fn zirOpaqueDecl(
989 sema: *Sema,
990 block: *Scope.Block,
991 inst: Zir.Inst.Index,
992 name_strategy: Zir.Inst.NameStrategy,
993) InnerError!*Inst {
942994 const tracy = trace(@src());
943995 defer tracy.end();
944996
......@@ -949,7 +1001,12 @@ fn zirOpaqueDecl(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerEr
9491001 return sema.mod.fail(&block.base, sema.src, "TODO implement zirOpaqueDecl", .{});
9501002}
9511003
952fn zirErrorSetDecl(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
1004fn zirErrorSetDecl(
1005 sema: *Sema,
1006 block: *Scope.Block,
1007 inst: Zir.Inst.Index,
1008 name_strategy: Zir.Inst.NameStrategy,
1009) InnerError!*Inst {
9531010 const tracy = trace(@src());
9541011 defer tracy.end();
9551012
src/Zir.zig+363-228
......@@ -296,34 +296,16 @@ pub const Inst = struct {
296296 /// only the taken branch is analyzed. The then block and else block must
297297 /// terminate with an "inline" variant of a noreturn instruction.
298298 condbr_inline,
299 /// A struct type definition. Contains references to ZIR instructions for
300 /// the field types, defaults, and alignments.
301 /// Uses the `pl_node` union field. Payload is `StructDecl`.
302 struct_decl,
303 /// Same as `struct_decl`, except has the `packed` layout.
304 struct_decl_packed,
305 /// Same as `struct_decl`, except has the `extern` layout.
306 struct_decl_extern,
307 /// A union type definition. Contains references to ZIR instructions for
308 /// the field types and optional type tag expression.
309 /// Uses the `pl_node` union field. Payload is `UnionDecl`.
310 union_decl,
311 /// Same as `union_decl`, except has the `packed` layout.
312 union_decl_packed,
313 /// Same as `union_decl`, except has the `extern` layout.
314 union_decl_extern,
315 /// An enum type definition. Contains references to ZIR instructions for
316 /// the field value expressions and optional type tag expression.
317 /// Uses the `pl_node` union field. Payload is `EnumDecl`.
318 enum_decl,
319 /// Same as `enum_decl`, except the enum is non-exhaustive.
320 enum_decl_nonexhaustive,
321299 /// An opaque type definition. Provides an AST node only.
322300 /// Uses the `pl_node` union field. Payload is `OpaqueDecl`.
323301 opaque_decl,
302 opaque_decl_anon,
303 opaque_decl_func,
324304 /// An error set type definition. Contains a list of field names.
325305 /// Uses the `pl_node` union field. Payload is `ErrorSetDecl`.
326306 error_set_decl,
307 error_set_decl_anon,
308 error_set_decl_func,
327309 /// Declares the beginning of a statement. Used for debug info.
328310 /// Uses the `dbg_stmt` union field. The line and column are offset
329311 /// from the parent declaration.
......@@ -1011,16 +993,12 @@ pub const Inst = struct {
1011993 .cmp_gt,
1012994 .cmp_neq,
1013995 .coerce_result_ptr,
1014 .struct_decl,
1015 .struct_decl_packed,
1016 .struct_decl_extern,
1017 .union_decl,
1018 .union_decl_packed,
1019 .union_decl_extern,
1020 .enum_decl,
1021 .enum_decl_nonexhaustive,
1022996 .opaque_decl,
997 .opaque_decl_anon,
998 .opaque_decl_func,
1023999 .error_set_decl,
1000 .error_set_decl_anon,
1001 .error_set_decl_func,
10241002 .dbg_stmt,
10251003 .decl_ref,
10261004 .decl_val,
......@@ -1271,16 +1249,12 @@ pub const Inst = struct {
12711249 .coerce_result_ptr = .bin,
12721250 .condbr = .pl_node,
12731251 .condbr_inline = .pl_node,
1274 .struct_decl = .pl_node,
1275 .struct_decl_packed = .pl_node,
1276 .struct_decl_extern = .pl_node,
1277 .union_decl = .pl_node,
1278 .union_decl_packed = .pl_node,
1279 .union_decl_extern = .pl_node,
1280 .enum_decl = .pl_node,
1281 .enum_decl_nonexhaustive = .pl_node,
12821252 .opaque_decl = .pl_node,
1253 .opaque_decl_anon = .pl_node,
1254 .opaque_decl_func = .pl_node,
12831255 .error_set_decl = .pl_node,
1256 .error_set_decl_anon = .pl_node,
1257 .error_set_decl_func = .pl_node,
12841258 .dbg_stmt = .dbg_stmt,
12851259 .decl_ref = .str_tok,
12861260 .decl_val = .str_tok,
......@@ -1507,6 +1481,21 @@ pub const Inst = struct {
15071481 /// `operand` is payload index to `ExtendedVar`.
15081482 /// `small` is `ExtendedVar.Small`.
15091483 variable,
1484 /// A struct type definition. Contains references to ZIR instructions for
1485 /// the field types, defaults, and alignments.
1486 /// `operand` is payload index to `StructDecl`.
1487 /// `small` is `StructDecl.Small`.
1488 struct_decl,
1489 /// An enum type definition. Contains references to ZIR instructions for
1490 /// the field value expressions and optional type tag expression.
1491 /// `operand` is payload index to `EnumDecl`.
1492 /// `small` is `EnumDecl.Small`.
1493 enum_decl,
1494 /// A union type definition. Contains references to ZIR instructions for
1495 /// the field types and optional type tag expression.
1496 /// `operand` is payload index to `UnionDecl`.
1497 /// `small` is `UnionDecl.Small`.
1498 union_decl,
15101499 /// Obtains a pointer to the return value.
15111500 /// `operand` is `src_node: i32`.
15121501 ret_ptr,
......@@ -2251,9 +2240,9 @@ pub const Inst = struct {
22512240 body_len: u32,
22522241
22532242 pub const SrcLocs = struct {
2254 /// Absolute line number in the source file.
2243 /// Absolute line index in the source file.
22552244 lbrace_line: u32,
2256 /// Absolute line number in the source file.
2245 /// Absolute line index in the source file.
22572246 rbrace_line: u32,
22582247 /// lbrace_column is least significant bits u16
22592248 /// rbrace_column is most significant bits u16
......@@ -2414,13 +2403,17 @@ pub const Inst = struct {
24142403 };
24152404
24162405 /// Trailing:
2417 /// 0. decl_bits: u32 // for every 8 decls
2406 /// 0. src_node: i32, // if has_src_node
2407 /// 1. body_len: u32, // if has_body_len
2408 /// 2. fields_len: u32, // if has_fields_len
2409 /// 3. decls_len: u32, // if has_decls_len
2410 /// 4. decl_bits: u32 // for every 8 decls
24182411 /// - sets of 4 bits:
24192412 /// 0b000X: whether corresponding decl is pub
24202413 /// 0b00X0: whether corresponding decl is exported
24212414 /// 0b0X00: whether corresponding decl has an align expression
24222415 /// 0bX000: whether corresponding decl has a linksection expression
2423 /// 1. decl: { // for every decls_len
2416 /// 5. decl: { // for every decls_len
24242417 /// src_hash: [4]u32, // hash of source bytes
24252418 /// line: u32, // line number of decl, relative to parent
24262419 /// name: u32, // null terminated string index
......@@ -2433,14 +2426,14 @@ pub const Inst = struct {
24332426 /// align: Ref, // if corresponding bit is set
24342427 /// link_section: Ref, // if corresponding bit is set
24352428 /// }
2436 /// 2. inst: Index // for every body_len
2437 /// 3. flags: u32 // for every 8 fields
2429 /// 6. inst: Index // for every body_len
2430 /// 7. flags: u32 // for every 8 fields
24382431 /// - sets of 4 bits:
24392432 /// 0b000X: whether corresponding field has an align expression
24402433 /// 0b00X0: whether corresponding field has a default expression
24412434 /// 0b0X00: whether corresponding field is comptime
24422435 /// 0bX000: unused
2443 /// 4. fields: { // for every fields_len
2436 /// 8. fields: { // for every fields_len
24442437 /// field_name: u32,
24452438 /// field_type: Ref,
24462439 /// - if none, means `anytype`.
......@@ -2448,19 +2441,42 @@ pub const Inst = struct {
24482441 /// default_value: Ref, // if corresponding bit is set
24492442 /// }
24502443 pub const StructDecl = struct {
2451 body_len: u32,
2452 fields_len: u32,
2453 decls_len: u32,
2444 pub const Small = packed struct {
2445 has_src_node: bool,
2446 has_body_len: bool,
2447 has_fields_len: bool,
2448 has_decls_len: bool,
2449 name_strategy: NameStrategy,
2450 layout: std.builtin.TypeInfo.ContainerLayout,
2451 _: u8 = undefined,
2452 };
2453 };
2454
2455 pub const NameStrategy = enum(u2) {
2456 /// Use the same name as the parent declaration name.
2457 /// e.g. `const Foo = struct {...};`.
2458 parent,
2459 /// Use the name of the currently executing comptime function call,
2460 /// with the current parameters. e.g. `ArrayList(i32)`.
2461 func,
2462 /// Create an anonymous name for this declaration.
2463 /// Like this: "ParentDeclName_struct_69"
2464 anon,
24542465 };
24552466
24562467 /// Trailing:
2457 /// 0. decl_bits: u32 // for every 8 decls
2468 /// 0. src_node: i32, // if has_src_node
2469 /// 1. tag_type: Ref, // if has_tag_type
2470 /// 2. body_len: u32, // if has_body_len
2471 /// 3. fields_len: u32, // if has_fields_len
2472 /// 4. decls_len: u32, // if has_decls_len
2473 /// 5. decl_bits: u32 // for every 8 decls
24582474 /// - sets of 4 bits:
24592475 /// 0b000X: whether corresponding decl is pub
24602476 /// 0b00X0: whether corresponding decl is exported
24612477 /// 0b0X00: whether corresponding decl has an align expression
24622478 /// 0bX000: whether corresponding decl has a linksection expression
2463 /// 1. decl: { // for every decls_len
2479 /// 6. decl: { // for every decls_len
24642480 /// src_hash: [4]u32, // hash of source bytes
24652481 /// line: u32, // line number of decl, relative to parent
24662482 /// name: u32, // null terminated string index
......@@ -2473,29 +2489,39 @@ pub const Inst = struct {
24732489 /// align: Ref, // if corresponding bit is set
24742490 /// link_section: Ref, // if corresponding bit is set
24752491 /// }
2476 /// 2. inst: Index // for every body_len
2477 /// 3. has_bits: u32 // for every 32 fields
2492 /// 7. inst: Index // for every body_len
2493 /// 8. has_bits: u32 // for every 32 fields
24782494 /// - the bit is whether corresponding field has an value expression
2479 /// 4. fields: { // for every fields_len
2495 /// 9. fields: { // for every fields_len
24802496 /// field_name: u32,
24812497 /// value: Ref, // if corresponding bit is set
24822498 /// }
24832499 pub const EnumDecl = struct {
2484 /// Can be `Ref.none`.
2485 tag_type: Ref,
2486 body_len: u32,
2487 fields_len: u32,
2488 decls_len: u32,
2500 pub const Small = packed struct {
2501 has_src_node: bool,
2502 has_tag_type: bool,
2503 has_body_len: bool,
2504 has_fields_len: bool,
2505 has_decls_len: bool,
2506 name_strategy: NameStrategy,
2507 nonexhaustive: bool,
2508 _: u8 = undefined,
2509 };
24892510 };
24902511
24912512 /// Trailing:
2492 /// 0. decl_bits: u32 // for every 8 decls
2513 /// 0. src_node: i32, // if has_src_node
2514 /// 1. tag_type: Ref, // if has_tag_type
2515 /// 2. body_len: u32, // if has_body_len
2516 /// 3. fields_len: u32, // if has_fields_len
2517 /// 4. decls_len: u32, // if has_decls_len
2518 /// 5. decl_bits: u32 // for every 8 decls
24932519 /// - sets of 4 bits:
24942520 /// 0b000X: whether corresponding decl is pub
24952521 /// 0b00X0: whether corresponding decl is exported
24962522 /// 0b0X00: whether corresponding decl has an align expression
24972523 /// 0bX000: whether corresponding decl has a linksection expression
2498 /// 1. decl: { // for every decls_len
2524 /// 6. decl: { // for every decls_len
24992525 /// src_hash: [4]u32, // hash of source bytes
25002526 /// line: u32, // line number of decl, relative to parent
25012527 /// name: u32, // null terminated string index
......@@ -2508,29 +2534,33 @@ pub const Inst = struct {
25082534 /// align: Ref, // if corresponding bit is set
25092535 /// link_section: Ref, // if corresponding bit is set
25102536 /// }
2511 /// 2. inst: Index // for every body_len
2512 /// 3. has_bits: u32 // for every 8 fields
2537 /// 7. inst: Index // for every body_len
2538 /// 8. has_bits: u32 // for every 8 fields
25132539 /// - sets of 4 bits:
25142540 /// 0b000X: whether corresponding field has a type expression
25152541 /// 0b00X0: whether corresponding field has a align expression
25162542 /// 0b0X00: whether corresponding field has a tag value expression
2517 /// 0bX000: unused(*)
2518 /// * the first unused bit (the unused bit of the first field) is used
2519 /// to indicate whether auto enum tag is enabled.
2520 /// 0 = union(tag_type)
2521 /// 1 = union(enum(tag_type))
2522 /// 4. fields: { // for every fields_len
2543 /// 0bX000: unused
2544 /// 9. fields: { // for every fields_len
25232545 /// field_name: u32, // null terminated string index
25242546 /// field_type: Ref, // if corresponding bit is set
25252547 /// align: Ref, // if corresponding bit is set
25262548 /// tag_value: Ref, // if corresponding bit is set
25272549 /// }
25282550 pub const UnionDecl = struct {
2529 /// Can be `Ref.none`.
2530 tag_type: Ref,
2531 body_len: u32,
2532 fields_len: u32,
2533 decls_len: u32,
2551 pub const Small = packed struct {
2552 has_src_node: bool,
2553 has_tag_type: bool,
2554 has_body_len: bool,
2555 has_fields_len: bool,
2556 has_decls_len: bool,
2557 name_strategy: NameStrategy,
2558 layout: std.builtin.TypeInfo.ContainerLayout,
2559 /// false: union(tag_type)
2560 /// true: union(enum(tag_type))
2561 auto_enum_tag: bool,
2562 _: u6 = undefined,
2563 };
25342564 };
25352565
25362566 /// Trailing:
......@@ -2901,8 +2931,6 @@ const Writer = struct {
29012931 .field_type => try self.writeFieldType(stream, inst),
29022932 .field_type_ref => try self.writeFieldTypeRef(stream, inst),
29032933
2904 .error_set_decl => try self.writePlNodeErrorSetDecl(stream, inst),
2905
29062934 .add,
29072935 .addwrap,
29082936 .array_cat,
......@@ -2980,21 +3008,13 @@ const Writer = struct {
29803008 .condbr_inline,
29813009 => try self.writePlNodeCondBr(stream, inst),
29823010
2983 .struct_decl,
2984 .struct_decl_packed,
2985 .struct_decl_extern,
2986 => try self.writeStructDecl(stream, inst),
2987
2988 .union_decl,
2989 .union_decl_packed,
2990 .union_decl_extern,
2991 => try self.writeUnionDecl(stream, inst),
2992
2993 .enum_decl,
2994 .enum_decl_nonexhaustive,
2995 => try self.writeEnumDecl(stream, inst),
3011 .opaque_decl => try self.writeOpaqueDecl(stream, inst, .parent),
3012 .opaque_decl_anon => try self.writeOpaqueDecl(stream, inst, .anon),
3013 .opaque_decl_func => try self.writeOpaqueDecl(stream, inst, .func),
29963014
2997 .opaque_decl => try self.writeOpaqueDecl(stream, inst),
3015 .error_set_decl => try self.writeErrorSetDecl(stream, inst, .parent),
3016 .error_set_decl_anon => try self.writeErrorSetDecl(stream, inst, .anon),
3017 .error_set_decl_func => try self.writeErrorSetDecl(stream, inst, .func),
29983018
29993019 .switch_block => try self.writePlNodeSwitchBr(stream, inst, .none),
30003020 .switch_block_else => try self.writePlNodeSwitchBr(stream, inst, .@"else"),
......@@ -3080,6 +3100,10 @@ const Writer = struct {
30803100 .shl_with_overflow,
30813101 => try self.writeOverflowArithmetic(stream, extended),
30823102
3103 .struct_decl => try self.writeStructDecl(stream, extended),
3104 .union_decl => try self.writeUnionDecl(stream, extended),
3105 .enum_decl => try self.writeEnumDecl(stream, extended),
3106
30833107 .alloc,
30843108 .builtin_extern,
30853109 .c_undef,
......@@ -3315,25 +3339,6 @@ const Writer = struct {
33153339 try self.writeSrc(stream, inst_data.src());
33163340 }
33173341
3318 fn writePlNodeErrorSetDecl(self: *Writer, stream: anytype, inst: Inst.Index) !void {
3319 const inst_data = self.code.instructions.items(.data)[inst].pl_node;
3320 const extra = self.code.extraData(Inst.ErrorSetDecl, inst_data.payload_index);
3321 const fields = self.code.extra[extra.end..][0..extra.data.fields_len];
3322
3323 try stream.writeAll("{\n");
3324 self.indent += 2;
3325 for (fields) |str_index| {
3326 const name = self.code.nullTerminatedString(str_index);
3327 try stream.writeByteNTimes(' ', self.indent);
3328 try stream.print("{},\n", .{std.zig.fmtId(name)});
3329 }
3330 self.indent -= 2;
3331 try stream.writeByteNTimes(' ', self.indent);
3332 try stream.writeAll("}) ");
3333
3334 try self.writeSrc(stream, inst_data.src());
3335 }
3336
33373342 fn writeNodeMultiOp(self: *Writer, stream: anytype, extended: Inst.Extended.InstData) !void {
33383343 const extra = self.code.extraData(Inst.NodeMultiOp, extended.operand);
33393344 const src: LazySrcLoc = .{ .node_offset = extra.data.src_node };
......@@ -3483,33 +3488,56 @@ const Writer = struct {
34833488 try self.writeSrc(stream, inst_data.src());
34843489 }
34853490
3486 fn writeStructDecl(self: *Writer, stream: anytype, inst: Inst.Index) !void {
3487 const inst_data = self.code.instructions.items(.data)[inst].pl_node;
3488 const extra = self.code.extraData(Inst.StructDecl, inst_data.payload_index);
3489 const fields_len = extra.data.fields_len;
3490 const decls_len = extra.data.decls_len;
3491 fn writeStructDecl(self: *Writer, stream: anytype, extended: Inst.Extended.InstData) !void {
3492 const small = @bitCast(Inst.StructDecl.Small, extended.small);
3493
3494 var extra_index: usize = extended.operand;
3495
3496 const src_node: ?i32 = if (small.has_src_node) blk: {
3497 const src_node = @bitCast(i32, self.code.extra[extra_index]);
3498 extra_index += 1;
3499 break :blk src_node;
3500 } else null;
3501
3502 const body_len = if (small.has_body_len) blk: {
3503 const body_len = self.code.extra[extra_index];
3504 extra_index += 1;
3505 break :blk body_len;
3506 } else 0;
34913507
3492 var extra_index: usize = undefined;
3508 const fields_len = if (small.has_fields_len) blk: {
3509 const fields_len = self.code.extra[extra_index];
3510 extra_index += 1;
3511 break :blk fields_len;
3512 } else 0;
3513
3514 const decls_len = if (small.has_decls_len) blk: {
3515 const decls_len = self.code.extra[extra_index];
3516 extra_index += 1;
3517 break :blk decls_len;
3518 } else 0;
3519
3520 try stream.print("{s}, {s}, ", .{
3521 @tagName(small.name_strategy), @tagName(small.layout),
3522 });
34933523
34943524 if (decls_len == 0) {
34953525 try stream.writeAll("{}, ");
3496 extra_index = extra.end;
34973526 } else {
34983527 try stream.writeAll("{\n");
34993528 self.indent += 2;
3500 extra_index = try self.writeDecls(stream, decls_len, extra.end);
3529 extra_index = try self.writeDecls(stream, decls_len, extra_index);
35013530 self.indent -= 2;
35023531 try stream.writeByteNTimes(' ', self.indent);
35033532 try stream.writeAll("}, ");
35043533 }
35053534
3506 const body = self.code.extra[extra_index..][0..extra.data.body_len];
3535 const body = self.code.extra[extra_index..][0..body_len];
35073536 extra_index += body.len;
35083537
35093538 if (fields_len == 0) {
35103539 assert(body.len == 0);
3511 try stream.writeAll("{}, {}) ");
3512 extra_index = extra.end;
3540 try stream.writeAll("{}, {})");
35133541 } else {
35143542 self.indent += 2;
35153543 if (body.len == 0) {
......@@ -3575,41 +3603,70 @@ const Writer = struct {
35753603
35763604 self.indent -= 2;
35773605 try stream.writeByteNTimes(' ', self.indent);
3578 try stream.writeAll("}) ");
3606 try stream.writeAll("})");
35793607 }
3580 try self.writeSrc(stream, inst_data.src());
3608 try self.writeSrcNode(stream, src_node);
35813609 }
35823610
3583 fn writeUnionDecl(self: *Writer, stream: anytype, inst: Inst.Index) !void {
3584 const inst_data = self.code.instructions.items(.data)[inst].pl_node;
3585 const extra = self.code.extraData(Inst.UnionDecl, inst_data.payload_index);
3586 const fields_len = extra.data.fields_len;
3587 const decls_len = extra.data.decls_len;
3588 const tag_type_ref = extra.data.tag_type;
3611 fn writeUnionDecl(self: *Writer, stream: anytype, extended: Inst.Extended.InstData) !void {
3612 const small = @bitCast(Inst.UnionDecl.Small, extended.small);
3613
3614 var extra_index: usize = extended.operand;
3615
3616 const src_node: ?i32 = if (small.has_src_node) blk: {
3617 const src_node = @bitCast(i32, self.code.extra[extra_index]);
3618 extra_index += 1;
3619 break :blk src_node;
3620 } else null;
3621
3622 const tag_type_ref = if (small.has_tag_type) blk: {
3623 const tag_type_ref = @intToEnum(Zir.Inst.Ref, self.code.extra[extra_index]);
3624 extra_index += 1;
3625 break :blk tag_type_ref;
3626 } else .none;
3627
3628 const body_len = if (small.has_body_len) blk: {
3629 const body_len = self.code.extra[extra_index];
3630 extra_index += 1;
3631 break :blk body_len;
3632 } else 0;
3633
3634 const fields_len = if (small.has_fields_len) blk: {
3635 const fields_len = self.code.extra[extra_index];
3636 extra_index += 1;
3637 break :blk fields_len;
3638 } else 0;
35893639
3590 var extra_index: usize = undefined;
3640 const decls_len = if (small.has_decls_len) blk: {
3641 const decls_len = self.code.extra[extra_index];
3642 extra_index += 1;
3643 break :blk decls_len;
3644 } else 0;
3645
3646 try stream.print("{s}, {s}, ", .{
3647 @tagName(small.name_strategy), @tagName(small.layout),
3648 });
3649 try self.writeFlag(stream, "autoenum, ", small.auto_enum_tag);
35913650
35923651 if (decls_len == 0) {
35933652 try stream.writeAll("{}, ");
3594 extra_index = extra.end;
35953653 } else {
35963654 try stream.writeAll("{\n");
35973655 self.indent += 2;
3598 extra_index = try self.writeDecls(stream, decls_len, extra.end);
3656 extra_index = try self.writeDecls(stream, decls_len, extra_index);
35993657 self.indent -= 2;
36003658 try stream.writeByteNTimes(' ', self.indent);
36013659 try stream.writeAll("}, ");
36023660 }
36033661
36043662 assert(fields_len != 0);
3605 var first_has_auto_enum: ?bool = null;
36063663
36073664 if (tag_type_ref != .none) {
36083665 try self.writeInstRef(stream, tag_type_ref);
36093666 try stream.writeAll(", ");
36103667 }
36113668
3612 const body = self.code.extra[extra_index..][0..extra.data.body_len];
3669 const body = self.code.extra[extra_index..][0..body_len];
36133670 extra_index += body.len;
36143671
36153672 self.indent += 2;
......@@ -3642,12 +3699,10 @@ const Writer = struct {
36423699 cur_bit_bag >>= 1;
36433700 const has_value = @truncate(u1, cur_bit_bag) != 0;
36443701 cur_bit_bag >>= 1;
3645 const has_auto_enum = @truncate(u1, cur_bit_bag) != 0;
3702 const unused = @truncate(u1, cur_bit_bag) != 0;
36463703 cur_bit_bag >>= 1;
36473704
3648 if (first_has_auto_enum == null) {
3649 first_has_auto_enum = has_auto_enum;
3650 }
3705 _ = unused;
36513706
36523707 const field_name = self.code.nullTerminatedString(self.code.extra[extra_index]);
36533708 extra_index += 1;
......@@ -3681,10 +3736,8 @@ const Writer = struct {
36813736
36823737 self.indent -= 2;
36833738 try stream.writeByteNTimes(' ', self.indent);
3684 try stream.writeAll("}");
3685 try self.writeFlag(stream, ", autoenum", first_has_auto_enum.?);
3686 try stream.writeAll(") ");
3687 try self.writeSrc(stream, inst_data.src());
3739 try stream.writeAll("})");
3740 try self.writeSrcNode(stream, src_node);
36883741 }
36893742
36903743 fn writeDecls(self: *Writer, stream: anytype, decls_len: u32, extra_start: usize) !usize {
......@@ -3776,22 +3829,49 @@ const Writer = struct {
37763829 return extra_index;
37773830 }
37783831
3779 fn writeEnumDecl(self: *Writer, stream: anytype, inst: Inst.Index) !void {
3780 const inst_data = self.code.instructions.items(.data)[inst].pl_node;
3781 const extra = self.code.extraData(Inst.EnumDecl, inst_data.payload_index);
3782 const fields_len = extra.data.fields_len;
3783 const decls_len = extra.data.decls_len;
3784 const tag_type_ref = extra.data.tag_type;
3832 fn writeEnumDecl(self: *Writer, stream: anytype, extended: Inst.Extended.InstData) !void {
3833 const small = @bitCast(Inst.EnumDecl.Small, extended.small);
3834 var extra_index: usize = extended.operand;
3835
3836 const src_node: ?i32 = if (small.has_src_node) blk: {
3837 const src_node = @bitCast(i32, self.code.extra[extra_index]);
3838 extra_index += 1;
3839 break :blk src_node;
3840 } else null;
3841
3842 const tag_type_ref = if (small.has_tag_type) blk: {
3843 const tag_type_ref = @intToEnum(Zir.Inst.Ref, self.code.extra[extra_index]);
3844 extra_index += 1;
3845 break :blk tag_type_ref;
3846 } else .none;
3847
3848 const body_len = if (small.has_body_len) blk: {
3849 const body_len = self.code.extra[extra_index];
3850 extra_index += 1;
3851 break :blk body_len;
3852 } else 0;
3853
3854 const fields_len = if (small.has_fields_len) blk: {
3855 const fields_len = self.code.extra[extra_index];
3856 extra_index += 1;
3857 break :blk fields_len;
3858 } else 0;
3859
3860 const decls_len = if (small.has_decls_len) blk: {
3861 const decls_len = self.code.extra[extra_index];
3862 extra_index += 1;
3863 break :blk decls_len;
3864 } else 0;
37853865
3786 var extra_index: usize = undefined;
3866 try stream.print("{s}, ", .{@tagName(small.name_strategy)});
3867 try self.writeFlag(stream, "nonexhaustive, ", small.nonexhaustive);
37873868
37883869 if (decls_len == 0) {
37893870 try stream.writeAll("{}, ");
3790 extra_index = extra.end;
37913871 } else {
37923872 try stream.writeAll("{\n");
37933873 self.indent += 2;
3794 extra_index = try self.writeDecls(stream, decls_len, extra.end);
3874 extra_index = try self.writeDecls(stream, decls_len, extra_index);
37953875 self.indent -= 2;
37963876 try stream.writeByteNTimes(' ', self.indent);
37973877 try stream.writeAll("}, ");
......@@ -3802,12 +3882,12 @@ const Writer = struct {
38023882 try stream.writeAll(", ");
38033883 }
38043884
3805 const body = self.code.extra[extra_index..][0..extra.data.body_len];
3885 const body = self.code.extra[extra_index..][0..body_len];
38063886 extra_index += body.len;
38073887
38083888 if (fields_len == 0) {
38093889 assert(body.len == 0);
3810 try stream.writeAll("{}, {}) ");
3890 try stream.writeAll("{}, {})");
38113891 } else {
38123892 self.indent += 2;
38133893 if (body.len == 0) {
......@@ -3851,16 +3931,23 @@ const Writer = struct {
38513931 }
38523932 self.indent -= 2;
38533933 try stream.writeByteNTimes(' ', self.indent);
3854 try stream.writeAll("}) ");
3934 try stream.writeAll("})");
38553935 }
3856 try self.writeSrc(stream, inst_data.src());
3936 try self.writeSrcNode(stream, src_node);
38573937 }
38583938
3859 fn writeOpaqueDecl(self: *Writer, stream: anytype, inst: Inst.Index) !void {
3939 fn writeOpaqueDecl(
3940 self: *Writer,
3941 stream: anytype,
3942 inst: Inst.Index,
3943 name_strategy: Inst.NameStrategy,
3944 ) !void {
38603945 const inst_data = self.code.instructions.items(.data)[inst].pl_node;
38613946 const extra = self.code.extraData(Inst.OpaqueDecl, inst_data.payload_index);
38623947 const decls_len = extra.data.decls_len;
38633948
3949 try stream.print("{s}, ", .{@tagName(name_strategy)});
3950
38643951 if (decls_len == 0) {
38653952 try stream.writeAll("}) ");
38663953 } else {
......@@ -3874,6 +3961,32 @@ const Writer = struct {
38743961 try self.writeSrc(stream, inst_data.src());
38753962 }
38763963
3964 fn writeErrorSetDecl(
3965 self: *Writer,
3966 stream: anytype,
3967 inst: Inst.Index,
3968 name_strategy: Inst.NameStrategy,
3969 ) !void {
3970 const inst_data = self.code.instructions.items(.data)[inst].pl_node;
3971 const extra = self.code.extraData(Inst.ErrorSetDecl, inst_data.payload_index);
3972 const fields = self.code.extra[extra.end..][0..extra.data.fields_len];
3973
3974 try stream.print("{s}, ", .{@tagName(name_strategy)});
3975
3976 try stream.writeAll("{\n");
3977 self.indent += 2;
3978 for (fields) |str_index| {
3979 const name = self.code.nullTerminatedString(str_index);
3980 try stream.writeByteNTimes(' ', self.indent);
3981 try stream.print("{},\n", .{std.zig.fmtId(name)});
3982 }
3983 self.indent -= 2;
3984 try stream.writeByteNTimes(' ', self.indent);
3985 try stream.writeAll("}) ");
3986
3987 try self.writeSrc(stream, inst_data.src());
3988 }
3989
38773990 fn writePlNodeSwitchBr(
38783991 self: *Writer,
38793992 stream: anytype,
......@@ -4337,6 +4450,13 @@ const Writer = struct {
43374450 });
43384451 }
43394452
4453 fn writeSrcNode(self: *Writer, stream: anytype, src_node: ?i32) !void {
4454 const node_offset = src_node orelse return;
4455 const src: LazySrcLoc = .{ .node_offset = node_offset };
4456 try stream.writeAll(" ");
4457 return self.writeSrc(stream, src);
4458 }
4459
43404460 fn writeBody(self: *Writer, stream: anytype, body: []const Inst.Index) !void {
43414461 for (body) |inst| {
43424462 try stream.writeByteNTimes(' ', self.indent);
......@@ -4389,75 +4509,86 @@ pub const DeclIterator = struct {
43894509pub fn declIterator(zir: Zir, decl_inst: u32) DeclIterator {
43904510 const tags = zir.instructions.items(.tag);
43914511 const datas = zir.instructions.items(.data);
4392 const decl_info: struct {
4393 extra_index: usize,
4394 decls_len: u32,
4395 } = switch (tags[decl_inst]) {
4396 .struct_decl,
4397 .struct_decl_packed,
4398 .struct_decl_extern,
4399 => blk: {
4400 const inst_data = datas[decl_inst].pl_node;
4401 const extra = zir.extraData(Inst.StructDecl, inst_data.payload_index);
4402 break :blk .{
4403 .extra_index = extra.end,
4404 .decls_len = extra.data.decls_len,
4405 };
4406 },
4407
4408 .union_decl,
4409 .union_decl_packed,
4410 .union_decl_extern,
4411 => blk: {
4412 const inst_data = datas[decl_inst].pl_node;
4413 const extra = zir.extraData(Inst.UnionDecl, inst_data.payload_index);
4414 break :blk .{
4415 .extra_index = extra.end,
4416 .decls_len = extra.data.decls_len,
4417 };
4418 },
4419
4420 .enum_decl,
4421 .enum_decl_nonexhaustive,
4422 => blk: {
4423 const inst_data = datas[decl_inst].pl_node;
4424 const extra = zir.extraData(Inst.EnumDecl, inst_data.payload_index);
4425 break :blk .{
4426 .extra_index = extra.end,
4427 .decls_len = extra.data.decls_len,
4428 };
4429 },
4430
4431 .opaque_decl => blk: {
4512 switch (tags[decl_inst]) {
4513 .opaque_decl,
4514 .opaque_decl_anon,
4515 .opaque_decl_func,
4516 => {
44324517 const inst_data = datas[decl_inst].pl_node;
44334518 const extra = zir.extraData(Inst.OpaqueDecl, inst_data.payload_index);
4434 break :blk .{
4435 .extra_index = extra.end,
4436 .decls_len = extra.data.decls_len,
4437 };
4519 return declIteratorInner(zir, extra.end, extra.data.decls_len);
44384520 },
44394521
44404522 // Functions are allowed and yield no iterations.
4523 // There is one case matching this in the extended instruction set below.
44414524 .func,
44424525 .func_inferred,
4443 .extended, // assume also a function
4444 => .{
4445 .extra_index = 0,
4446 .decls_len = 0,
4447 },
4526 => return declIteratorInner(zir, 0, 0),
44484527
4528 .extended => {
4529 const extended = datas[decl_inst].extended;
4530 switch (extended.opcode) {
4531 .func => return declIteratorInner(zir, 0, 0),
4532 .struct_decl => {
4533 const small = @bitCast(Inst.StructDecl.Small, extended.small);
4534 var extra_index: usize = extended.operand;
4535 extra_index += @boolToInt(small.has_src_node);
4536 extra_index += @boolToInt(small.has_body_len);
4537 extra_index += @boolToInt(small.has_fields_len);
4538 const decls_len = if (small.has_decls_len) decls_len: {
4539 const decls_len = zir.extra[extra_index];
4540 extra_index += 1;
4541 break :decls_len decls_len;
4542 } else 0;
4543
4544 return declIteratorInner(zir, extra_index, decls_len);
4545 },
4546 .enum_decl => {
4547 const small = @bitCast(Inst.EnumDecl.Small, extended.small);
4548 var extra_index: usize = extended.operand;
4549 extra_index += @boolToInt(small.has_src_node);
4550 extra_index += @boolToInt(small.has_tag_type);
4551 extra_index += @boolToInt(small.has_body_len);
4552 extra_index += @boolToInt(small.has_fields_len);
4553 const decls_len = if (small.has_decls_len) decls_len: {
4554 const decls_len = zir.extra[extra_index];
4555 extra_index += 1;
4556 break :decls_len decls_len;
4557 } else 0;
4558
4559 return declIteratorInner(zir, extra_index, decls_len);
4560 },
4561 .union_decl => {
4562 const small = @bitCast(Inst.UnionDecl.Small, extended.small);
4563 var extra_index: usize = extended.operand;
4564 extra_index += @boolToInt(small.has_src_node);
4565 extra_index += @boolToInt(small.has_tag_type);
4566 extra_index += @boolToInt(small.has_body_len);
4567 extra_index += @boolToInt(small.has_fields_len);
4568 const decls_len = if (small.has_decls_len) decls_len: {
4569 const decls_len = zir.extra[extra_index];
4570 extra_index += 1;
4571 break :decls_len decls_len;
4572 } else 0;
4573
4574 return declIteratorInner(zir, extra_index, decls_len);
4575 },
4576 else => unreachable,
4577 }
4578 },
44494579 else => unreachable,
4450 };
4451
4452 const bit_bags_count = std.math.divCeil(usize, decl_info.decls_len, 8) catch unreachable;
4580 }
4581}
44534582
4583pub fn declIteratorInner(zir: Zir, extra_index: usize, decls_len: u32) DeclIterator {
4584 const bit_bags_count = std.math.divCeil(usize, decls_len, 8) catch unreachable;
44544585 return .{
44554586 .zir = zir,
4456 .extra_index = decl_info.extra_index + bit_bags_count,
4457 .bit_bag_index = decl_info.extra_index,
4587 .extra_index = extra_index + bit_bags_count,
4588 .bit_bag_index = extra_index,
44584589 .cur_bit_bag = undefined,
44594590 .decl_i = 0,
4460 .decls_len = decl_info.decls_len,
4591 .decls_len = decls_len,
44614592 };
44624593}
44634594
......@@ -4480,15 +4611,10 @@ fn findDeclsInner(
44804611
44814612 switch (tags[inst]) {
44824613 // Decl instructions are interesting but have no body.
4483 .struct_decl,
4484 .struct_decl_packed,
4485 .struct_decl_extern,
4486 .union_decl,
4487 .union_decl_packed,
4488 .union_decl_extern,
4489 .enum_decl,
4490 .enum_decl_nonexhaustive,
4614 // TODO yes they do have a body actually. recurse over them just like block instructions.
44914615 .opaque_decl,
4616 .opaque_decl_anon,
4617 .opaque_decl_func,
44924618 => return list.append(inst),
44934619
44944620 // Functions instructions are interesting and have a body.
......@@ -4505,19 +4631,28 @@ fn findDeclsInner(
45054631 },
45064632 .extended => {
45074633 const extended = datas[inst].extended;
4508 if (extended.opcode != .func) return;
4634 switch (extended.opcode) {
4635 .func => {
4636 try list.append(inst);
4637
4638 const extra = zir.extraData(Inst.ExtendedFunc, extended.operand);
4639 const small = @bitCast(Inst.ExtendedFunc.Small, extended.small);
4640 var extra_index: usize = extra.end;
4641 extra_index += @boolToInt(small.has_lib_name);
4642 extra_index += @boolToInt(small.has_cc);
4643 extra_index += @boolToInt(small.has_align);
4644 extra_index += extra.data.param_types_len;
4645 const body = zir.extra[extra_index..][0..extra.data.body_len];
4646 return zir.findDeclsBody(list, body);
4647 },
45094648
4510 try list.append(inst);
4649 .struct_decl,
4650 .union_decl,
4651 .enum_decl,
4652 => return list.append(inst),
45114653
4512 const extra = zir.extraData(Inst.ExtendedFunc, extended.operand);
4513 const small = @bitCast(Inst.ExtendedFunc.Small, extended.small);
4514 var extra_index: usize = extra.end;
4515 extra_index += @boolToInt(small.has_lib_name);
4516 extra_index += @boolToInt(small.has_cc);
4517 extra_index += @boolToInt(small.has_align);
4518 extra_index += extra.data.param_types_len;
4519 const body = zir.extra[extra_index..][0..extra.data.body_len];
4520 return zir.findDeclsBody(list, body);
4654 else => return,
4655 }
45214656 },
45224657
45234658 // Block instructions, recurse over the bodies.