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 @@...@@ -65,3 +65,6 @@
65 * use ZIR memory for decl names where possible and also for keys65 * use ZIR memory for decl names where possible and also for keys
66 - this will require more sophisticated changelist detection which does some66 - this will require more sophisticated changelist detection which does some
67 pre-emptive deletion of decls from the parent namespace67 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) {...@@ -263,7 +263,7 @@ pub const TypeInfo = union(enum) {
263263
264 /// This data structure is used by the Zig language code generation and264 /// This data structure is used by the Zig language code generation and
265 /// therefore must be kept in sync with the compiler implementation.265 /// therefore must be kept in sync with the compiler implementation.
266 pub const ContainerLayout = enum {266 pub const ContainerLayout = enum(u2) {
267 Auto,267 Auto,
268 Extern,268 Extern,
269 Packed,269 Packed,
src/AstGen.zig+236-65
...@@ -85,6 +85,7 @@ pub fn generate(gpa: *Allocator, tree: ast.Tree) InnerError!Zir {...@@ -85,6 +85,7 @@ pub fn generate(gpa: *Allocator, tree: ast.Tree) InnerError!Zir {
85 var gen_scope: GenZir = .{85 var gen_scope: GenZir = .{
86 .force_comptime = true,86 .force_comptime = true,
87 .parent = null,87 .parent = null,
88 .anon_name_strategy = .parent,
88 .decl_node_index = 0,89 .decl_node_index = 0,
89 .decl_line = 0,90 .decl_line = 0,
90 .astgen = &astgen,91 .astgen = &astgen,
...@@ -105,7 +106,7 @@ pub fn generate(gpa: *Allocator, tree: ast.Tree) InnerError!Zir {...@@ -105,7 +106,7 @@ pub fn generate(gpa: *Allocator, tree: ast.Tree) InnerError!Zir {
105 &gen_scope.base,106 &gen_scope.base,
106 0,107 0,
107 container_decl,108 container_decl,
108 .struct_decl,109 .Auto,
109 )) |struct_decl_ref| {110 )) |struct_decl_ref| {
110 astgen.extra.items[@enumToInt(Zir.ExtraIndex.main_struct)] = @enumToInt(struct_decl_ref);111 astgen.extra.items[@enumToInt(Zir.ExtraIndex.main_struct)] = @enumToInt(struct_decl_ref);
111 } else |err| switch (err) {112 } else |err| switch (err) {
...@@ -1959,16 +1960,12 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: ast.Node.Index) Inner...@@ -1959,16 +1960,12 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: ast.Node.Index) Inner
1959 .union_init_ptr,1960 .union_init_ptr,
1960 .field_type,1961 .field_type,
1961 .field_type_ref,1962 .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,
1970 .opaque_decl,1963 .opaque_decl,
1964 .opaque_decl_anon,
1965 .opaque_decl_func,
1971 .error_set_decl,1966 .error_set_decl,
1967 .error_set_decl_anon,
1968 .error_set_decl_func,
1972 .int_to_enum,1969 .int_to_enum,
1973 .enum_to_int,1970 .enum_to_int,
1974 .type_info,1971 .type_info,
...@@ -2166,7 +2163,7 @@ fn varDecl(...@@ -2166,7 +2163,7 @@ fn varDecl(
2166 const local_val = s.cast(Scope.LocalVal).?;2163 const local_val = s.cast(Scope.LocalVal).?;
2167 if (local_val.name == ident_name) {2164 if (local_val.name == ident_name) {
2168 return astgen.failTokNotes(name_token, "redeclaration of '{s}'", .{2165 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),
2170 }, &[_]u32{2167 }, &[_]u32{
2171 try astgen.errNoteTok(2168 try astgen.errNoteTok(
2172 local_val.token_src,2169 local_val.token_src,
...@@ -2181,7 +2178,7 @@ fn varDecl(...@@ -2181,7 +2178,7 @@ fn varDecl(
2181 const local_ptr = s.cast(Scope.LocalPtr).?;2178 const local_ptr = s.cast(Scope.LocalPtr).?;
2182 if (local_ptr.name == ident_name) {2179 if (local_ptr.name == ident_name) {
2183 return astgen.failTokNotes(name_token, "redeclaration of '{s}'", .{2180 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),
2185 }, &[_]u32{2182 }, &[_]u32{
2186 try astgen.errNoteTok(2183 try astgen.errNoteTok(
2187 local_ptr.token_src,2184 local_ptr.token_src,
...@@ -2941,12 +2938,16 @@ fn globalVarDecl(...@@ -2941,12 +2938,16 @@ fn globalVarDecl(
2941 // of the top level declaration.2938 // of the top level declaration.
2942 const block_inst = try gz.addBlock(.block_inline, node);2939 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
2944 var block_scope: GenZir = .{2944 var block_scope: GenZir = .{
2945 .parent = scope,2945 .parent = scope,
2946 .decl_node_index = node,2946 .decl_node_index = node,
2947 .decl_line = gz.calcLine(node),2947 .decl_line = gz.calcLine(node),
2948 .astgen = astgen,2948 .astgen = astgen,
2949 .force_comptime = true,2949 .force_comptime = true,
2950 .anon_name_strategy = .parent,
2950 };2951 };
2951 defer block_scope.instructions.deinit(gpa);2952 defer block_scope.instructions.deinit(gpa);
29522953
...@@ -3043,9 +3044,6 @@ fn globalVarDecl(...@@ -3043,9 +3044,6 @@ fn globalVarDecl(
3043 _ = try block_scope.addBreak(.break_inline, block_inst, var_inst);3044 _ = try block_scope.addBreak(.break_inline, block_inst, var_inst);
3044 try block_scope.setBlockBody(block_inst);3045 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
3049 try wip_decls.payload.ensureUnusedCapacity(gpa, 9);3047 try wip_decls.payload.ensureUnusedCapacity(gpa, 9);
3050 {3048 {
3051 const contents_hash = std.zig.hashSrc(tree.getNodeSource(node));3049 const contents_hash = std.zig.hashSrc(tree.getNodeSource(node));
...@@ -3258,14 +3256,18 @@ fn structDeclInner(...@@ -3258,14 +3256,18 @@ fn structDeclInner(
3258 scope: *Scope,3256 scope: *Scope,
3259 node: ast.Node.Index,3257 node: ast.Node.Index,
3260 container_decl: ast.full.ContainerDecl,3258 container_decl: ast.full.ContainerDecl,
3261 tag: Zir.Inst.Tag,3259 layout: std.builtin.TypeInfo.ContainerLayout,
3262) InnerError!Zir.Inst.Ref {3260) InnerError!Zir.Inst.Ref {
3263 if (container_decl.ast.members.len == 0) {3261 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,
3265 .fields_len = 0,3266 .fields_len = 0,
3266 .body_len = 0,3267 .body_len = 0,
3267 .decls_len = 0,3268 .decls_len = 0,
3268 });3269 });
3270 return gz.indexToRef(decl_inst);
3269 }3271 }
32703272
3271 const astgen = gz.astgen;3273 const astgen = gz.astgen;
...@@ -3437,23 +3439,24 @@ fn structDeclInner(...@@ -3437,23 +3439,24 @@ fn structDeclInner(
3437 }3439 }
3438 }3440 }
34393441
3440 const decl_inst = try gz.addBlock(tag, node);3442 const decl_inst = try gz.reserveInstructionIndex();
3441 try gz.instructions.append(gpa, decl_inst);
3442 if (block_scope.instructions.items.len != 0) {3443 if (block_scope.instructions.items.len != 0) {
3443 _ = try block_scope.addBreak(.break_inline, decl_inst, .void_value);3444 _ = try block_scope.addBreak(.break_inline, decl_inst, .void_value);
3444 }3445 }
34453446
3446 try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.StructDecl).Struct.fields.len +3447 try gz.setStruct(decl_inst, .{
3447 bit_bag.items.len + @boolToInt(field_index != 0) + fields_data.items.len +3448 .src_node = node,
3448 block_scope.instructions.items.len +3449 .layout = layout,
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{
3453 .body_len = @intCast(u32, block_scope.instructions.items.len),3450 .body_len = @intCast(u32, block_scope.instructions.items.len),
3454 .fields_len = @intCast(u32, field_index),3451 .fields_len = @intCast(u32, field_index),
3455 .decls_len = @intCast(u32, wip_decls.decl_index),3452 .decls_len = @intCast(u32, wip_decls.decl_index),
3456 });3453 });
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);
3457 astgen.extra.appendSliceAssumeCapacity(wip_decls.bit_bag.items); // Likely empty.3460 astgen.extra.appendSliceAssumeCapacity(wip_decls.bit_bag.items); // Likely empty.
3458 if (wip_decls.decl_index != 0) {3461 if (wip_decls.decl_index != 0) {
3459 astgen.extra.appendAssumeCapacity(wip_decls.cur_bit_bag);3462 astgen.extra.appendAssumeCapacity(wip_decls.cur_bit_bag);
...@@ -3476,7 +3479,7 @@ fn unionDeclInner(...@@ -3476,7 +3479,7 @@ fn unionDeclInner(
3476 scope: *Scope,3479 scope: *Scope,
3477 node: ast.Node.Index,3480 node: ast.Node.Index,
3478 members: []const ast.Node.Index,3481 members: []const ast.Node.Index,
3479 tag: Zir.Inst.Tag,3482 layout: std.builtin.TypeInfo.ContainerLayout,
3480 arg_inst: Zir.Inst.Ref,3483 arg_inst: Zir.Inst.Ref,
3481 have_auto_enum: bool,3484 have_auto_enum: bool,
3482) InnerError!Zir.Inst.Ref {3485) InnerError!Zir.Inst.Ref {
...@@ -3611,11 +3614,12 @@ fn unionDeclInner(...@@ -3611,11 +3614,12 @@ fn unionDeclInner(
3611 const have_type = member.ast.type_expr != 0;3614 const have_type = member.ast.type_expr != 0;
3612 const have_align = member.ast.align_expr != 0;3615 const have_align = member.ast.align_expr != 0;
3613 const have_value = member.ast.value_expr != 0;3616 const have_value = member.ast.value_expr != 0;
3617 const unused = false;
3614 cur_bit_bag = (cur_bit_bag >> bits_per_field) |3618 cur_bit_bag = (cur_bit_bag >> bits_per_field) |
3615 (@as(u32, @boolToInt(have_type)) << 28) |3619 (@as(u32, @boolToInt(have_type)) << 28) |
3616 (@as(u32, @boolToInt(have_align)) << 29) |3620 (@as(u32, @boolToInt(have_align)) << 29) |
3617 (@as(u32, @boolToInt(have_value)) << 30) |3621 (@as(u32, @boolToInt(have_value)) << 30) |
3618 (@as(u32, @boolToInt(have_auto_enum)) << 31);3622 (@as(u32, @boolToInt(unused)) << 31);
36193623
3620 if (have_type) {3624 if (have_type) {
3621 const field_type = try typeExpr(&block_scope, &block_scope.base, member.ast.type_expr);3625 const field_type = try typeExpr(&block_scope, &block_scope.base, member.ast.type_expr);
...@@ -3662,24 +3666,26 @@ fn unionDeclInner(...@@ -3662,24 +3666,26 @@ fn unionDeclInner(
3662 }3666 }
3663 }3667 }
36643668
3665 const decl_inst = try gz.addBlock(tag, node);3669 const decl_inst = try gz.reserveInstructionIndex();
3666 try gz.instructions.append(gpa, decl_inst);
3667 if (block_scope.instructions.items.len != 0) {3670 if (block_scope.instructions.items.len != 0) {
3668 _ = try block_scope.addBreak(.break_inline, decl_inst, .void_value);3671 _ = try block_scope.addBreak(.break_inline, decl_inst, .void_value);
3669 }3672 }
36703673
3671 try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.UnionDecl).Struct.fields.len +3674 try gz.setUnion(decl_inst, .{
3672 bit_bag.items.len + 1 + fields_data.items.len +3675 .src_node = node,
3673 block_scope.instructions.items.len +3676 .layout = layout,
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{
3678 .tag_type = arg_inst,3677 .tag_type = arg_inst,
3679 .body_len = @intCast(u32, block_scope.instructions.items.len),3678 .body_len = @intCast(u32, block_scope.instructions.items.len),
3680 .fields_len = @intCast(u32, field_index),3679 .fields_len = @intCast(u32, field_index),
3681 .decls_len = @intCast(u32, wip_decls.decl_index),3680 .decls_len = @intCast(u32, wip_decls.decl_index),
3681 .auto_enum_tag = have_auto_enum,
3682 });3682 });
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);
3683 astgen.extra.appendSliceAssumeCapacity(wip_decls.bit_bag.items); // Likely empty.3689 astgen.extra.appendSliceAssumeCapacity(wip_decls.bit_bag.items); // Likely empty.
3684 if (wip_decls.decl_index != 0) {3690 if (wip_decls.decl_index != 0) {
3685 astgen.extra.appendAssumeCapacity(wip_decls.cur_bit_bag);3691 astgen.extra.appendAssumeCapacity(wip_decls.cur_bit_bag);
...@@ -3719,29 +3725,27 @@ fn containerDecl(...@@ -3719,29 +3725,27 @@ fn containerDecl(
37193725
3720 switch (token_tags[container_decl.ast.main_token]) {3726 switch (token_tags[container_decl.ast.main_token]) {
3721 .keyword_struct => {3727 .keyword_struct => {
3722 const tag = if (container_decl.layout_token) |t| switch (token_tags[t]) {3728 const layout = if (container_decl.layout_token) |t| switch (token_tags[t]) {
3723 .keyword_packed => Zir.Inst.Tag.struct_decl_packed,3729 .keyword_packed => std.builtin.TypeInfo.ContainerLayout.Packed,
3724 .keyword_extern => Zir.Inst.Tag.struct_decl_extern,3730 .keyword_extern => std.builtin.TypeInfo.ContainerLayout.Extern,
3725 else => unreachable,3731 else => unreachable,
3726 } else Zir.Inst.Tag.struct_decl;3732 } else std.builtin.TypeInfo.ContainerLayout.Auto;
37273733
3728 assert(arg_inst == .none);3734 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);
3731 return rvalue(gz, scope, rl, result, node);3737 return rvalue(gz, scope, rl, result, node);
3732 },3738 },
3733 .keyword_union => {3739 .keyword_union => {
3734 const tag = if (container_decl.layout_token) |t| switch (token_tags[t]) {3740 const layout = if (container_decl.layout_token) |t| switch (token_tags[t]) {
3735 .keyword_packed => Zir.Inst.Tag.union_decl_packed,3741 .keyword_packed => std.builtin.TypeInfo.ContainerLayout.Packed,
3736 .keyword_extern => Zir.Inst.Tag.union_decl_extern,3742 .keyword_extern => std.builtin.TypeInfo.ContainerLayout.Extern,
3737 else => unreachable,3743 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.
3742 const have_auto_enum = container_decl.ast.enum_token != null;3746 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);
3745 return rvalue(gz, scope, rl, result, node);3749 return rvalue(gz, scope, rl, result, node);
3746 },3750 },
3747 .keyword_enum => {3751 .keyword_enum => {
...@@ -3832,10 +3836,7 @@ fn containerDecl(...@@ -3832,10 +3836,7 @@ fn containerDecl(
3832 }3836 }
3833 // In this case we must generate ZIR code for the tag values, similar to3837 // In this case we must generate ZIR code for the tag values, similar to
3834 // how structs are handled above.3838 // how structs are handled above.
3835 const tag: Zir.Inst.Tag = if (counts.nonexhaustive_node == 0)3839 const nonexhaustive = counts.nonexhaustive_node != 0;
3836 .enum_decl
3837 else
3838 .enum_decl_nonexhaustive;
38393840
3840 // The enum_decl instruction introduces a scope in which the decls of the enum3841 // The enum_decl instruction introduces a scope in which the decls of the enum
3841 // are in scope, so that tag values can refer to decls within the enum itself.3842 // are in scope, so that tag values can refer to decls within the enum itself.
...@@ -3995,24 +3996,25 @@ fn containerDecl(...@@ -3995,24 +3996,25 @@ fn containerDecl(
3995 }3996 }
3996 }3997 }
39973998
3998 const decl_inst = try gz.addBlock(tag, node);3999 const decl_inst = try gz.reserveInstructionIndex();
3999 try gz.instructions.append(gpa, decl_inst);
4000 if (block_scope.instructions.items.len != 0) {4000 if (block_scope.instructions.items.len != 0) {
4001 _ = try block_scope.addBreak(.break_inline, decl_inst, .void_value);4001 _ = try block_scope.addBreak(.break_inline, decl_inst, .void_value);
4002 }4002 }
40034003
4004 try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.EnumDecl).Struct.fields.len +4004 try gz.setEnum(decl_inst, .{
4005 bit_bag.items.len + 1 + fields_data.items.len +4005 .src_node = node,
4006 block_scope.instructions.items.len +4006 .nonexhaustive = nonexhaustive,
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{
4011 .tag_type = arg_inst,4007 .tag_type = arg_inst,
4012 .body_len = @intCast(u32, block_scope.instructions.items.len),4008 .body_len = @intCast(u32, block_scope.instructions.items.len),
4013 .fields_len = @intCast(u32, field_index),4009 .fields_len = @intCast(u32, field_index),
4014 .decls_len = @intCast(u32, wip_decls.decl_index),4010 .decls_len = @intCast(u32, wip_decls.decl_index),
4015 });4011 });
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);
4016 astgen.extra.appendSliceAssumeCapacity(wip_decls.bit_bag.items); // Likely empty.4018 astgen.extra.appendSliceAssumeCapacity(wip_decls.bit_bag.items); // Likely empty.
4017 if (wip_decls.decl_index != 0) {4019 if (wip_decls.decl_index != 0) {
4018 astgen.extra.appendAssumeCapacity(wip_decls.cur_bit_bag);4020 astgen.extra.appendAssumeCapacity(wip_decls.cur_bit_bag);
...@@ -4118,7 +4120,12 @@ fn containerDecl(...@@ -4118,7 +4120,12 @@ fn containerDecl(
4118 wip_decls.cur_bit_bag >>= @intCast(u5, empty_slot_count * WipDecls.bits_per_field);4120 wip_decls.cur_bit_bag >>= @intCast(u5, empty_slot_count * WipDecls.bits_per_field);
4119 }4121 }
4120 }4122 }
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);
4122 try gz.instructions.append(gpa, decl_inst);4129 try gz.instructions.append(gpa, decl_inst);
41234130
4124 try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.OpaqueDecl).Struct.fields.len +4131 try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.OpaqueDecl).Struct.fields.len +
...@@ -4173,6 +4180,11 @@ fn errorSetDecl(...@@ -4173,6 +4180,11 @@ fn errorSetDecl(
4173 }4180 }
4174 }4181 }
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 };
4176 const result = try gz.addPlNode(.error_set_decl, node, Zir.Inst.ErrorSetDecl{4188 const result = try gz.addPlNode(.error_set_decl, node, Zir.Inst.ErrorSetDecl{
4177 .fields_len = @intCast(u32, field_names.items.len),4189 .fields_len = @intCast(u32, field_names.items.len),
4178 });4190 });
...@@ -5907,7 +5919,6 @@ fn charLiteral(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index)...@@ -5907,7 +5919,6 @@ fn charLiteral(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index)
5907 const value = std.zig.parseCharLiteral(slice, &bad_index) catch |err| switch (err) {5919 const value = std.zig.parseCharLiteral(slice, &bad_index) catch |err| switch (err) {
5908 error.InvalidCharacter => {5920 error.InvalidCharacter => {
5909 const bad_byte = slice[bad_index];5921 const bad_byte = slice[bad_index];
5910 const token_starts = tree.tokens.items(.start);
5911 return astgen.failOff(5922 return astgen.failOff(
5912 main_token,5923 main_token,
5913 @intCast(u32, bad_index),5924 @intCast(u32, bad_index),
...@@ -7779,6 +7790,8 @@ const GenZir = struct {...@@ -7779,6 +7790,8 @@ const GenZir = struct {
7779 const base_tag: Scope.Tag = .gen_zir;7790 const base_tag: Scope.Tag = .gen_zir;
7780 base: Scope = Scope{ .tag = base_tag },7791 base: Scope = Scope{ .tag = base_tag },
7781 force_comptime: bool,7792 force_comptime: bool,
7793 /// How decls created in this scope should be named.
7794 anon_name_strategy: Zir.Inst.NameStrategy = .anon,
7782 /// The end of special indexes. `Zir.Inst.Ref` subtracts against this number to convert7795 /// The end of special indexes. `Zir.Inst.Ref` subtracts against this number to convert
7783 /// to `Zir.Inst.Index`. The default here is correct if there are 0 parameters.7796 /// to `Zir.Inst.Index`. The default here is correct if there are 0 parameters.
7784 ref_start_index: u32 = Zir.Inst.Ref.typed_value_map.len,7797 ref_start_index: u32 = Zir.Inst.Ref.typed_value_map.len,
...@@ -8623,18 +8636,176 @@ const GenZir = struct {...@@ -8623,18 +8636,176 @@ const GenZir = struct {
8623 return new_index;8636 return new_index;
8624 }8637 }
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
8626 fn add(gz: *GenZir, inst: Zir.Inst) !Zir.Inst.Ref {8780 fn add(gz: *GenZir, inst: Zir.Inst) !Zir.Inst.Ref {
8627 return gz.indexToRef(try gz.addAsIndex(inst));8781 return gz.indexToRef(try gz.addAsIndex(inst));
8628 }8782 }
86298783
8630 fn addAsIndex(gz: *GenZir, inst: Zir.Inst) !Zir.Inst.Index {8784 fn addAsIndex(gz: *GenZir, inst: Zir.Inst) !Zir.Inst.Index {
8631 const gpa = gz.astgen.gpa;8785 const gpa = gz.astgen.gpa;
8632 try gz.instructions.ensureCapacity(gpa, gz.instructions.items.len + 1);8786 try gz.instructions.ensureUnusedCapacity(gpa, 1);
8633 try gz.astgen.instructions.ensureCapacity(gpa, gz.astgen.instructions.len + 1);8787 try gz.astgen.instructions.ensureUnusedCapacity(gpa, 1);
86348788
8635 const new_index = @intCast(Zir.Inst.Index, gz.astgen.instructions.len);8789 const new_index = @intCast(Zir.Inst.Index, gz.astgen.instructions.len);
8636 gz.astgen.instructions.appendAssumeCapacity(inst);8790 gz.astgen.instructions.appendAssumeCapacity(inst);
8637 gz.instructions.appendAssumeCapacity(new_index);8791 gz.instructions.appendAssumeCapacity(new_index);
8638 return new_index;8792 return new_index;
8639 }8793 }
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 }
8640};8805};
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) = .{},...@@ -75,6 +75,8 @@ failed_files: std.AutoArrayHashMapUnmanaged(*Scope.File, ?*ErrorMsg) = .{},
75/// The ErrorMsg memory is owned by the `Export`, using Module's general purpose allocator.75/// The ErrorMsg memory is owned by the `Export`, using Module's general purpose allocator.
76failed_exports: std.AutoArrayHashMapUnmanaged(*Export, *ErrorMsg) = .{},76failed_exports: std.AutoArrayHashMapUnmanaged(*Export, *ErrorMsg) = .{},
7777
78next_anon_name_index: usize = 0,
79
78/// Candidates for deletion. After a semantic analysis update completes, this list80/// Candidates for deletion. After a semantic analysis update completes, this list
79/// contains Decls that need to be deleted if they end up having no references to them.81/// contains Decls that need to be deleted if they end up having no references to them.
80deletion_set: std.AutoArrayHashMapUnmanaged(*Decl, void) = .{},82deletion_set: std.AutoArrayHashMapUnmanaged(*Decl, void) = .{},
...@@ -884,8 +886,11 @@ pub const Scope = struct {...@@ -884,8 +886,11 @@ pub const Scope = struct {
884 /// Declaration order is preserved via entry order.886 /// Declaration order is preserved via entry order.
885 /// Key memory is owned by `decl.name`.887 /// Key memory is owned by `decl.name`.
886 /// TODO save memory with https://github.com/ziglang/zig/issues/8619.888 /// 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.
887 decls: std.StringArrayHashMapUnmanaged(*Decl) = .{},890 decls: std.StringArrayHashMapUnmanaged(*Decl) = .{},
888891
892 anon_decls: std.AutoArrayHashMapUnmanaged(*Decl, void) = .{},
893
889 pub fn deinit(ns: *Namespace, mod: *Module) void {894 pub fn deinit(ns: *Namespace, mod: *Module) void {
890 ns.clearDecls(mod);895 ns.clearDecls(mod);
891 ns.* = undefined;896 ns.* = undefined;
...@@ -899,15 +904,27 @@ pub const Scope = struct {...@@ -899,15 +904,27 @@ pub const Scope = struct {
899 var decls = ns.decls;904 var decls = ns.decls;
900 ns.decls = .{};905 ns.decls = .{};
901906
907 var anon_decls = ns.anon_decls;
908 ns.anon_decls = .{};
909
902 for (decls.items()) |entry| {910 for (decls.items()) |entry| {
903 entry.value.destroy(mod);911 entry.value.destroy(mod);
904 }912 }
905 decls.deinit(gpa);913 decls.deinit(gpa);
914
915 for (anon_decls.items()) |entry| {
916 entry.key.destroy(mod);
917 }
918 anon_decls.deinit(gpa);
906 }919 }
907920
908 pub fn removeDecl(ns: *Namespace, child: *Decl) void {921 pub fn removeDecl(ns: *Namespace, child: *Decl) void {
909 // Preserve declaration order.922 if (child.zir_decl_index == 0) {
910 _ = ns.decls.orderedRemove(mem.spanZ(child.name));923 _ = ns.anon_decls.swapRemove(child);
924 } else {
925 // Preserve declaration order.
926 _ = ns.decls.orderedRemove(mem.spanZ(child.name));
927 }
911 }928 }
912929
913 // This renders e.g. "std.fs.Dir.OpenOptions"930 // This renders e.g. "std.fs.Dir.OpenOptions"
...@@ -2607,10 +2624,14 @@ fn updateZirRefs(gpa: *Allocator, file: *Scope.File, old_zir: Zir) !void {...@@ -2607,10 +2624,14 @@ fn updateZirRefs(gpa: *Allocator, file: *Scope.File, old_zir: Zir) !void {
2607 }2624 }
26082625
2609 if (decl.getInnerNamespace()) |namespace| {2626 if (decl.getInnerNamespace()) |namespace| {
2610 for (namespace.decls.items()) |*entry| {2627 for (namespace.decls.items()) |entry| {
2611 const sub_decl = entry.value;2628 const sub_decl = entry.value;
2612 try decl_stack.append(gpa, sub_decl);2629 try decl_stack.append(gpa, sub_decl);
2613 }2630 }
2631 for (namespace.anon_decls.items()) |entry| {
2632 const sub_decl = entry.key;
2633 try decl_stack.append(gpa, sub_decl);
2634 }
2614 }2635 }
2615 }2636 }
2616}2637}
...@@ -3741,31 +3762,17 @@ pub fn constIntBig(mod: *Module, arena: *Allocator, src: LazySrcLoc, ty: Type, b...@@ -3741,31 +3762,17 @@ pub fn constIntBig(mod: *Module, arena: *Allocator, src: LazySrcLoc, ty: Type, b
3741pub fn createAnonymousDecl(mod: *Module, scope: *Scope, typed_value: TypedValue) !*Decl {3762pub fn createAnonymousDecl(mod: *Module, scope: *Scope, typed_value: TypedValue) !*Decl {
3742 const scope_decl = scope.ownerDecl().?;3763 const scope_decl = scope.ownerDecl().?;
3743 const namespace = scope_decl.namespace;3764 const namespace = scope_decl.namespace;
3744 try namespace.decls.ensureUnusedCapacity(mod.gpa, 1);3765 try namespace.anon_decls.ensureUnusedCapacity(mod.gpa, 1);
37453766
3746 // Find a unique name for the anon decl.3767 const name_index = mod.getNextAnonNameIndex();
3747 var name_buf = std.ArrayList(u8).init(mod.gpa);3768 const name = try std.fmt.allocPrintZ(mod.gpa, "{s}__anon_{d}", .{
3748 defer name_buf.deinit();3769 scope_decl.name, name_index,
37493770 });
3750 try name_buf.appendSlice(mem.spanZ(scope_decl.name));3771 errdefer mod.gpa.free(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 }
37633772
3764 name_buf.clearRetainingCapacity();3773 const new_decl = try mod.allocateNewDecl(namespace, scope_decl.src_node);
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)
37683774
3775 new_decl.name = name;
3769 new_decl.src_line = scope_decl.src_line;3776 new_decl.src_line = scope_decl.src_line;
3770 new_decl.ty = typed_value.ty;3777 new_decl.ty = typed_value.ty;
3771 new_decl.val = typed_value.val;3778 new_decl.val = typed_value.val;
...@@ -3773,6 +3780,8 @@ pub fn createAnonymousDecl(mod: *Module, scope: *Scope, typed_value: TypedValue)...@@ -3773,6 +3780,8 @@ pub fn createAnonymousDecl(mod: *Module, scope: *Scope, typed_value: TypedValue)
3773 new_decl.analysis = .complete;3780 new_decl.analysis = .complete;
3774 new_decl.generation = mod.generation;3781 new_decl.generation = mod.generation;
37753782
3783 namespace.anon_decls.putAssumeCapacityNoClobber(new_decl, {});
3784
3776 // TODO: This generates the Decl into the machine code file if it is of a3785 // TODO: This generates the Decl into the machine code file if it is of a
3777 // type that is non-zero size. We should be able to further improve the3786 // type that is non-zero size. We should be able to further improve the
3778 // compiler to omit Decls which are only referenced at compile-time and not runtime.3787 // 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)...@@ -3784,6 +3793,10 @@ pub fn createAnonymousDecl(mod: *Module, scope: *Scope, typed_value: TypedValue)
3784 return new_decl;3793 return new_decl;
3785}3794}
37863795
3796fn getNextAnonNameIndex(mod: *Module) usize {
3797 return @atomicRmw(usize, &mod.next_anon_name_index, .Add, 1, .Monotonic);
3798}
3799
3787/// This looks up a bare identifier in the given scope. This will walk up the tree of namespaces3800/// This looks up a bare identifier in the given scope. This will walk up the tree of namespaces
3788/// in scope and check each one for the identifier.3801/// in scope and check each one for the identifier.
3789/// TODO emit a compile error if more than one decl would be matched.3802/// 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 {...@@ -4394,18 +4407,38 @@ pub fn analyzeStructFields(mod: *Module, struct_obj: *Struct) InnerError!void {
43944407
4395 const gpa = mod.gpa;4408 const gpa = mod.gpa;
4396 const zir = struct_obj.owner_decl.namespace.file_scope.zir;4409 const zir = struct_obj.owner_decl.namespace.file_scope.zir;
4397 const inst_data = zir.instructions.items(.data)[struct_obj.zir_index].pl_node;4410 const extended = zir.instructions.items(.data)[struct_obj.zir_index].extended;
4398 const src = inst_data.src();4411 assert(extended.opcode == .struct_decl);
4399 const extra = zir.extraData(Zir.Inst.StructDecl, inst_data.payload_index);4412 const small = @bitCast(Zir.Inst.StructDecl.Small, extended.small);
4400 const fields_len = extra.data.fields_len;4413 var extra_index: usize = extended.operand;
4401 const decls_len = extra.data.decls_len;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
4403 // Skip over decls.4436 // Skip over decls.
4404 var decls_it = zir.declIterator(struct_obj.zir_index);4437 var decls_it = zir.declIteratorInner(extra_index, decls_len);
4405 while (decls_it.next()) |_| {}4438 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];
4409 if (fields_len == 0) {4442 if (fields_len == 0) {
4410 assert(body.len == 0);4443 assert(body.len == 0);
4411 return;4444 return;
...@@ -4525,18 +4558,44 @@ pub fn analyzeUnionFields(mod: *Module, union_obj: *Union) InnerError!void {...@@ -4525,18 +4558,44 @@ pub fn analyzeUnionFields(mod: *Module, union_obj: *Union) InnerError!void {
45254558
4526 const gpa = mod.gpa;4559 const gpa = mod.gpa;
4527 const zir = union_obj.owner_decl.namespace.file_scope.zir;4560 const zir = union_obj.owner_decl.namespace.file_scope.zir;
4528 const inst_data = zir.instructions.items(.data)[union_obj.zir_index].pl_node;4561 const extended = zir.instructions.items(.data)[union_obj.zir_index].extended;
4529 const src = inst_data.src();4562 assert(extended.opcode == .union_decl);
4530 const extra = zir.extraData(Zir.Inst.UnionDecl, inst_data.payload_index);4563 const small = @bitCast(Zir.Inst.UnionDecl.Small, extended.small);
4531 const fields_len = extra.data.fields_len;4564 var extra_index: usize = extended.operand;
4532 const decls_len = extra.data.decls_len;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
4534 // Skip over decls.4593 // Skip over decls.
4535 var decls_it = zir.declIterator(union_obj.zir_index);4594 var decls_it = zir.declIteratorInner(extra_index, decls_len);
4536 while (decls_it.next()) |_| {}4595 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];
4540 if (fields_len == 0) {4599 if (fields_len == 0) {
4541 assert(body.len == 0);4600 assert(body.len == 0);
4542 return;4601 return;
...@@ -4580,8 +4639,6 @@ pub fn analyzeUnionFields(mod: *Module, union_obj: *Union) InnerError!void {...@@ -4580,8 +4639,6 @@ pub fn analyzeUnionFields(mod: *Module, union_obj: *Union) InnerError!void {
4580 _ = try sema.analyzeBody(&block, body);4639 _ = try sema.analyzeBody(&block, body);
4581 }4640 }
45824641
4583 var auto_enum_tag: ?bool = null;
4584
4585 const bits_per_field = 4;4642 const bits_per_field = 4;
4586 const fields_per_u32 = 32 / bits_per_field;4643 const fields_per_u32 = 32 / bits_per_field;
4587 const bit_bags_count = std.math.divCeil(usize, fields_len, fields_per_u32) catch unreachable;4644 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 {...@@ -4603,10 +4660,6 @@ pub fn analyzeUnionFields(mod: *Module, union_obj: *Union) InnerError!void {
4603 const unused = @truncate(u1, cur_bit_bag) != 0;4660 const unused = @truncate(u1, cur_bit_bag) != 0;
4604 cur_bit_bag >>= 1;4661 cur_bit_bag >>= 1;
46054662
4606 if (auto_enum_tag == null) {
4607 auto_enum_tag = unused;
4608 }
4609
4610 const field_name_zir = zir.nullTerminatedString(zir.extra[extra_index]);4663 const field_name_zir = zir.nullTerminatedString(zir.extra[extra_index]);
4611 extra_index += 1;4664 extra_index += 1;
46124665
...@@ -4653,7 +4706,7 @@ pub fn analyzeUnionFields(mod: *Module, union_obj: *Union) InnerError!void {...@@ -4653,7 +4706,7 @@ pub fn analyzeUnionFields(mod: *Module, union_obj: *Union) InnerError!void {
4653 }4706 }
4654 }4707 }
46554708
4656 // TODO resolve the union tag type4709 // TODO resolve the union tag_type_ref
4657}4710}
46584711
4659/// Called from `performAllTheWork`, after all AstGen workers have finished,4712/// Called from `performAllTheWork`, after all AstGen workers have finished,
src/Sema.zig+104-47
...@@ -350,16 +350,12 @@ pub fn analyzeBody(...@@ -350,16 +350,12 @@ pub fn analyzeBody(
350 .trunc => try sema.zirUnaryMath(block, inst),350 .trunc => try sema.zirUnaryMath(block, inst),
351 .round => try sema.zirUnaryMath(block, inst),351 .round => try sema.zirUnaryMath(block, inst),
352352
353 .struct_decl => try sema.zirStructDecl(block, inst, .Auto),353 .opaque_decl => try sema.zirOpaqueDecl(block, inst, .parent),
354 .struct_decl_packed => try sema.zirStructDecl(block, inst, .Packed),354 .opaque_decl_anon => try sema.zirOpaqueDecl(block, inst, .anon),
355 .struct_decl_extern => try sema.zirStructDecl(block, inst, .Extern),355 .opaque_decl_func => try sema.zirOpaqueDecl(block, inst, .func),
356 .enum_decl => try sema.zirEnumDecl(block, inst, false),356 .error_set_decl => try sema.zirErrorSetDecl(block, inst, .parent),
357 .enum_decl_nonexhaustive => try sema.zirEnumDecl(block, inst, true),357 .error_set_decl_anon => try sema.zirErrorSetDecl(block, inst, .anon),
358 .union_decl => try sema.zirUnionDecl(block, inst, .Auto),358 .error_set_decl_func => try sema.zirErrorSetDecl(block, inst, .func),
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),
363359
364 .add => try sema.zirArithmetic(block, inst),360 .add => try sema.zirArithmetic(block, inst),
365 .addwrap => try sema.zirArithmetic(block, inst),361 .addwrap => try sema.zirArithmetic(block, inst),
...@@ -515,6 +511,9 @@ fn zirExtended(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerErro...@@ -515,6 +511,9 @@ fn zirExtended(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerErro
515 // zig fmt: off511 // zig fmt: off
516 .func => return sema.zirFuncExtended( block, extended, inst),512 .func => return sema.zirFuncExtended( block, extended, inst),
517 .variable => return sema.zirVarExtended( block, extended),513 .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),
518 .ret_ptr => return sema.zirRetPtr( block, extended),517 .ret_ptr => return sema.zirRetPtr( block, extended),
519 .ret_type => return sema.zirRetType( block, extended),518 .ret_type => return sema.zirRetType( block, extended),
520 .this => return sema.zirThis( block, extended),519 .this => return sema.zirThis( block, extended),
...@@ -686,21 +685,34 @@ pub fn analyzeStructDecl(...@@ -686,21 +685,34 @@ pub fn analyzeStructDecl(
686 inst: Zir.Inst.Index,685 inst: Zir.Inst.Index,
687 struct_obj: *Module.Struct,686 struct_obj: *Module.Struct,
688) InnerError!void {687) InnerError!void {
689 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;688 const extended = sema.code.instructions.items(.data)[inst].extended;
690 const extra = sema.code.extraData(Zir.Inst.StructDecl, inst_data.payload_index);689 assert(extended.opcode == .struct_decl);
691 const decls_len = extra.data.decls_len;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);
694}703}
695704
696fn zirStructDecl(705fn zirStructDecl(
697 sema: *Sema,706 sema: *Sema,
698 block: *Scope.Block,707 block: *Scope.Block,
708 extended: Zir.Inst.Extended.InstData,
699 inst: Zir.Inst.Index,709 inst: Zir.Inst.Index,
700 layout: std.builtin.TypeInfo.ContainerLayout,
701) InnerError!*Inst {710) InnerError!*Inst {
702 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;711 const small = @bitCast(Zir.Inst.StructDecl.Small, extended.small);
703 const src = inst_data.src();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
705 var new_decl_arena = std.heap.ArenaAllocator.init(sema.gpa);717 var new_decl_arena = std.heap.ArenaAllocator.init(sema.gpa);
706718
...@@ -714,9 +726,9 @@ fn zirStructDecl(...@@ -714,9 +726,9 @@ fn zirStructDecl(
714 struct_obj.* = .{726 struct_obj.* = .{
715 .owner_decl = new_decl,727 .owner_decl = new_decl,
716 .fields = .{},728 .fields = .{},
717 .node_offset = inst_data.src_node,729 .node_offset = src.node_offset,
718 .zir_index = inst,730 .zir_index = inst,
719 .layout = layout,731 .layout = small.layout,
720 .status = .none,732 .status = .none,
721 .namespace = .{733 .namespace = .{
722 .parent = sema.owner_decl.namespace,734 .parent = sema.owner_decl.namespace,
...@@ -735,27 +747,53 @@ fn zirStructDecl(...@@ -735,27 +747,53 @@ fn zirStructDecl(
735fn zirEnumDecl(747fn zirEnumDecl(
736 sema: *Sema,748 sema: *Sema,
737 block: *Scope.Block,749 block: *Scope.Block,
738 inst: Zir.Inst.Index,750 extended: Zir.Inst.Extended.InstData,
739 nonexhaustive: bool,
740) InnerError!*Inst {751) InnerError!*Inst {
741 const tracy = trace(@src());752 const tracy = trace(@src());
742 defer tracy.end();753 defer tracy.end();
743754
744 const gpa = sema.gpa;755 const gpa = sema.gpa;
745 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;756 const small = @bitCast(Zir.Inst.EnumDecl.Small, extended.small);
746 const src = inst_data.src();757 var extra_index: usize = extended.operand;
747 const extra = sema.code.extraData(Zir.Inst.EnumDecl, inst_data.payload_index);758
748 const fields_len = extra.data.fields_len;759 const src: LazySrcLoc = if (small.has_src_node) blk: {
749 const decls_len = extra.data.decls_len;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
751 var new_decl_arena = std.heap.ArenaAllocator.init(gpa);789 var new_decl_arena = std.heap.ArenaAllocator.init(gpa);
752790
753 const tag_ty = blk: {791 const tag_ty = blk: {
754 if (extra.data.tag_type != .none) {792 if (tag_type_ref != .none) {
755 // TODO better source location793 // TODO better source location
756 // TODO (needs AstGen fix too) move this eval to the block so it gets allocated794 // TODO (needs AstGen fix too) move this eval to the block so it gets allocated
757 // in the new decl arena.795 // 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);
759 }797 }
760 const bits = std.math.log2_int_ceil(usize, fields_len);798 const bits = std.math.log2_int_ceil(usize, fields_len);
761 break :blk try Type.Tag.int_unsigned.create(&new_decl_arena.allocator, bits);799 break :blk try Type.Tag.int_unsigned.create(&new_decl_arena.allocator, bits);
...@@ -764,7 +802,7 @@ fn zirEnumDecl(...@@ -764,7 +802,7 @@ fn zirEnumDecl(
764 const enum_obj = try new_decl_arena.allocator.create(Module.EnumFull);802 const enum_obj = try new_decl_arena.allocator.create(Module.EnumFull);
765 const enum_ty_payload = try new_decl_arena.allocator.create(Type.Payload.EnumFull);803 const enum_ty_payload = try new_decl_arena.allocator.create(Type.Payload.EnumFull);
766 enum_ty_payload.* = .{804 enum_ty_payload.* = .{
767 .base = .{ .tag = if (nonexhaustive) .enum_nonexhaustive else .enum_full },805 .base = .{ .tag = if (small.nonexhaustive) .enum_nonexhaustive else .enum_full },
768 .data = enum_obj,806 .data = enum_obj,
769 };807 };
770 const enum_ty = Type.initPayload(&enum_ty_payload.base);808 const enum_ty = Type.initPayload(&enum_ty_payload.base);
...@@ -778,7 +816,7 @@ fn zirEnumDecl(...@@ -778,7 +816,7 @@ fn zirEnumDecl(
778 .tag_ty = tag_ty,816 .tag_ty = tag_ty,
779 .fields = .{},817 .fields = .{},
780 .values = .{},818 .values = .{},
781 .node_offset = inst_data.src_node,819 .node_offset = src.node_offset,
782 .namespace = .{820 .namespace = .{
783 .parent = sema.owner_decl.namespace,821 .parent = sema.owner_decl.namespace,
784 .ty = enum_ty,822 .ty = enum_ty,
...@@ -789,14 +827,9 @@ fn zirEnumDecl(...@@ -789,14 +827,9 @@ fn zirEnumDecl(
789 &enum_obj.namespace, new_decl, new_decl.name,827 &enum_obj.namespace, new_decl, new_decl.name,
790 });828 });
791829
792 var extra_index: usize = try sema.mod.scanNamespace(830 extra_index = try sema.mod.scanNamespace(&enum_obj.namespace, extra_index, decls_len, new_decl);
793 &enum_obj.namespace,
794 extra.end,
795 decls_len,
796 new_decl,
797 );
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];
800 if (fields_len == 0) {833 if (fields_len == 0) {
801 assert(body.len == 0);834 assert(body.len == 0);
802 try new_decl.finalizeNewArena(&new_decl_arena);835 try new_decl.finalizeNewArena(&new_decl_arena);
...@@ -894,16 +927,30 @@ fn zirEnumDecl(...@@ -894,16 +927,30 @@ fn zirEnumDecl(
894fn zirUnionDecl(927fn zirUnionDecl(
895 sema: *Sema,928 sema: *Sema,
896 block: *Scope.Block,929 block: *Scope.Block,
930 extended: Zir.Inst.Extended.InstData,
897 inst: Zir.Inst.Index,931 inst: Zir.Inst.Index,
898 layout: std.builtin.TypeInfo.ContainerLayout,
899) InnerError!*Inst {932) InnerError!*Inst {
900 const tracy = trace(@src());933 const tracy = trace(@src());
901 defer tracy.end();934 defer tracy.end();
902935
903 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;936 const small = @bitCast(Zir.Inst.UnionDecl.Small, extended.small);
904 const src = inst_data.src();937 var extra_index: usize = extended.operand;
905 const extra = sema.code.extraData(Zir.Inst.UnionDecl, inst_data.payload_index);938
906 const decls_len = extra.data.decls_len;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
908 var new_decl_arena = std.heap.ArenaAllocator.init(sema.gpa);955 var new_decl_arena = std.heap.ArenaAllocator.init(sema.gpa);
909956
...@@ -918,9 +965,9 @@ fn zirUnionDecl(...@@ -918,9 +965,9 @@ fn zirUnionDecl(
918 .owner_decl = new_decl,965 .owner_decl = new_decl,
919 .tag_ty = Type.initTag(.@"null"),966 .tag_ty = Type.initTag(.@"null"),
920 .fields = .{},967 .fields = .{},
921 .node_offset = inst_data.src_node,968 .node_offset = src.node_offset,
922 .zir_index = inst,969 .zir_index = inst,
923 .layout = layout,970 .layout = small.layout,
924 .status = .none,971 .status = .none,
925 .namespace = .{972 .namespace = .{
926 .parent = sema.owner_decl.namespace,973 .parent = sema.owner_decl.namespace,
...@@ -932,13 +979,18 @@ fn zirUnionDecl(...@@ -932,13 +979,18 @@ fn zirUnionDecl(
932 &union_obj.namespace, new_decl, new_decl.name,979 &union_obj.namespace, new_decl, new_decl.name,
933 });980 });
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
937 try new_decl.finalizeNewArena(&new_decl_arena);984 try new_decl.finalizeNewArena(&new_decl_arena);
938 return sema.analyzeDeclVal(block, src, new_decl);985 return sema.analyzeDeclVal(block, src, new_decl);
939}986}
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 {
942 const tracy = trace(@src());994 const tracy = trace(@src());
943 defer tracy.end();995 defer tracy.end();
944996
...@@ -949,7 +1001,12 @@ fn zirOpaqueDecl(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerEr...@@ -949,7 +1001,12 @@ fn zirOpaqueDecl(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerEr
949 return sema.mod.fail(&block.base, sema.src, "TODO implement zirOpaqueDecl", .{});1001 return sema.mod.fail(&block.base, sema.src, "TODO implement zirOpaqueDecl", .{});
950}1002}
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 {
953 const tracy = trace(@src());1010 const tracy = trace(@src());
954 defer tracy.end();1011 defer tracy.end();
9551012
src/Zir.zig+363-228
...@@ -296,34 +296,16 @@ pub const Inst = struct {...@@ -296,34 +296,16 @@ pub const Inst = struct {
296 /// only the taken branch is analyzed. The then block and else block must296 /// only the taken branch is analyzed. The then block and else block must
297 /// terminate with an "inline" variant of a noreturn instruction.297 /// terminate with an "inline" variant of a noreturn instruction.
298 condbr_inline,298 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,
321 /// An opaque type definition. Provides an AST node only.299 /// An opaque type definition. Provides an AST node only.
322 /// Uses the `pl_node` union field. Payload is `OpaqueDecl`.300 /// Uses the `pl_node` union field. Payload is `OpaqueDecl`.
323 opaque_decl,301 opaque_decl,
302 opaque_decl_anon,
303 opaque_decl_func,
324 /// An error set type definition. Contains a list of field names.304 /// An error set type definition. Contains a list of field names.
325 /// Uses the `pl_node` union field. Payload is `ErrorSetDecl`.305 /// Uses the `pl_node` union field. Payload is `ErrorSetDecl`.
326 error_set_decl,306 error_set_decl,
307 error_set_decl_anon,
308 error_set_decl_func,
327 /// Declares the beginning of a statement. Used for debug info.309 /// Declares the beginning of a statement. Used for debug info.
328 /// Uses the `dbg_stmt` union field. The line and column are offset310 /// Uses the `dbg_stmt` union field. The line and column are offset
329 /// from the parent declaration.311 /// from the parent declaration.
...@@ -1011,16 +993,12 @@ pub const Inst = struct {...@@ -1011,16 +993,12 @@ pub const Inst = struct {
1011 .cmp_gt,993 .cmp_gt,
1012 .cmp_neq,994 .cmp_neq,
1013 .coerce_result_ptr,995 .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,
1022 .opaque_decl,996 .opaque_decl,
997 .opaque_decl_anon,
998 .opaque_decl_func,
1023 .error_set_decl,999 .error_set_decl,
1000 .error_set_decl_anon,
1001 .error_set_decl_func,
1024 .dbg_stmt,1002 .dbg_stmt,
1025 .decl_ref,1003 .decl_ref,
1026 .decl_val,1004 .decl_val,
...@@ -1271,16 +1249,12 @@ pub const Inst = struct {...@@ -1271,16 +1249,12 @@ pub const Inst = struct {
1271 .coerce_result_ptr = .bin,1249 .coerce_result_ptr = .bin,
1272 .condbr = .pl_node,1250 .condbr = .pl_node,
1273 .condbr_inline = .pl_node,1251 .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,
1282 .opaque_decl = .pl_node,1252 .opaque_decl = .pl_node,
1253 .opaque_decl_anon = .pl_node,
1254 .opaque_decl_func = .pl_node,
1283 .error_set_decl = .pl_node,1255 .error_set_decl = .pl_node,
1256 .error_set_decl_anon = .pl_node,
1257 .error_set_decl_func = .pl_node,
1284 .dbg_stmt = .dbg_stmt,1258 .dbg_stmt = .dbg_stmt,
1285 .decl_ref = .str_tok,1259 .decl_ref = .str_tok,
1286 .decl_val = .str_tok,1260 .decl_val = .str_tok,
...@@ -1507,6 +1481,21 @@ pub const Inst = struct {...@@ -1507,6 +1481,21 @@ pub const Inst = struct {
1507 /// `operand` is payload index to `ExtendedVar`.1481 /// `operand` is payload index to `ExtendedVar`.
1508 /// `small` is `ExtendedVar.Small`.1482 /// `small` is `ExtendedVar.Small`.
1509 variable,1483 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,
1510 /// Obtains a pointer to the return value.1499 /// Obtains a pointer to the return value.
1511 /// `operand` is `src_node: i32`.1500 /// `operand` is `src_node: i32`.
1512 ret_ptr,1501 ret_ptr,
...@@ -2251,9 +2240,9 @@ pub const Inst = struct {...@@ -2251,9 +2240,9 @@ pub const Inst = struct {
2251 body_len: u32,2240 body_len: u32,
22522241
2253 pub const SrcLocs = struct {2242 pub const SrcLocs = struct {
2254 /// Absolute line number in the source file.2243 /// Absolute line index in the source file.
2255 lbrace_line: u32,2244 lbrace_line: u32,
2256 /// Absolute line number in the source file.2245 /// Absolute line index in the source file.
2257 rbrace_line: u32,2246 rbrace_line: u32,
2258 /// lbrace_column is least significant bits u162247 /// lbrace_column is least significant bits u16
2259 /// rbrace_column is most significant bits u162248 /// rbrace_column is most significant bits u16
...@@ -2414,13 +2403,17 @@ pub const Inst = struct {...@@ -2414,13 +2403,17 @@ pub const Inst = struct {
2414 };2403 };
24152404
2416 /// Trailing:2405 /// Trailing:
2417 /// 0. decl_bits: u32 // for every 8 decls2406 /// 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
2418 /// - sets of 4 bits:2411 /// - sets of 4 bits:
2419 /// 0b000X: whether corresponding decl is pub2412 /// 0b000X: whether corresponding decl is pub
2420 /// 0b00X0: whether corresponding decl is exported2413 /// 0b00X0: whether corresponding decl is exported
2421 /// 0b0X00: whether corresponding decl has an align expression2414 /// 0b0X00: whether corresponding decl has an align expression
2422 /// 0bX000: whether corresponding decl has a linksection expression2415 /// 0bX000: whether corresponding decl has a linksection expression
2423 /// 1. decl: { // for every decls_len2416 /// 5. decl: { // for every decls_len
2424 /// src_hash: [4]u32, // hash of source bytes2417 /// src_hash: [4]u32, // hash of source bytes
2425 /// line: u32, // line number of decl, relative to parent2418 /// line: u32, // line number of decl, relative to parent
2426 /// name: u32, // null terminated string index2419 /// name: u32, // null terminated string index
...@@ -2433,14 +2426,14 @@ pub const Inst = struct {...@@ -2433,14 +2426,14 @@ pub const Inst = struct {
2433 /// align: Ref, // if corresponding bit is set2426 /// align: Ref, // if corresponding bit is set
2434 /// link_section: Ref, // if corresponding bit is set2427 /// link_section: Ref, // if corresponding bit is set
2435 /// }2428 /// }
2436 /// 2. inst: Index // for every body_len2429 /// 6. inst: Index // for every body_len
2437 /// 3. flags: u32 // for every 8 fields2430 /// 7. flags: u32 // for every 8 fields
2438 /// - sets of 4 bits:2431 /// - sets of 4 bits:
2439 /// 0b000X: whether corresponding field has an align expression2432 /// 0b000X: whether corresponding field has an align expression
2440 /// 0b00X0: whether corresponding field has a default expression2433 /// 0b00X0: whether corresponding field has a default expression
2441 /// 0b0X00: whether corresponding field is comptime2434 /// 0b0X00: whether corresponding field is comptime
2442 /// 0bX000: unused2435 /// 0bX000: unused
2443 /// 4. fields: { // for every fields_len2436 /// 8. fields: { // for every fields_len
2444 /// field_name: u32,2437 /// field_name: u32,
2445 /// field_type: Ref,2438 /// field_type: Ref,
2446 /// - if none, means `anytype`.2439 /// - if none, means `anytype`.
...@@ -2448,19 +2441,42 @@ pub const Inst = struct {...@@ -2448,19 +2441,42 @@ pub const Inst = struct {
2448 /// default_value: Ref, // if corresponding bit is set2441 /// default_value: Ref, // if corresponding bit is set
2449 /// }2442 /// }
2450 pub const StructDecl = struct {2443 pub const StructDecl = struct {
2451 body_len: u32,2444 pub const Small = packed struct {
2452 fields_len: u32,2445 has_src_node: bool,
2453 decls_len: u32,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,
2454 };2465 };
24552466
2456 /// Trailing:2467 /// Trailing:
2457 /// 0. decl_bits: u32 // for every 8 decls2468 /// 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
2458 /// - sets of 4 bits:2474 /// - sets of 4 bits:
2459 /// 0b000X: whether corresponding decl is pub2475 /// 0b000X: whether corresponding decl is pub
2460 /// 0b00X0: whether corresponding decl is exported2476 /// 0b00X0: whether corresponding decl is exported
2461 /// 0b0X00: whether corresponding decl has an align expression2477 /// 0b0X00: whether corresponding decl has an align expression
2462 /// 0bX000: whether corresponding decl has a linksection expression2478 /// 0bX000: whether corresponding decl has a linksection expression
2463 /// 1. decl: { // for every decls_len2479 /// 6. decl: { // for every decls_len
2464 /// src_hash: [4]u32, // hash of source bytes2480 /// src_hash: [4]u32, // hash of source bytes
2465 /// line: u32, // line number of decl, relative to parent2481 /// line: u32, // line number of decl, relative to parent
2466 /// name: u32, // null terminated string index2482 /// name: u32, // null terminated string index
...@@ -2473,29 +2489,39 @@ pub const Inst = struct {...@@ -2473,29 +2489,39 @@ pub const Inst = struct {
2473 /// align: Ref, // if corresponding bit is set2489 /// align: Ref, // if corresponding bit is set
2474 /// link_section: Ref, // if corresponding bit is set2490 /// link_section: Ref, // if corresponding bit is set
2475 /// }2491 /// }
2476 /// 2. inst: Index // for every body_len2492 /// 7. inst: Index // for every body_len
2477 /// 3. has_bits: u32 // for every 32 fields2493 /// 8. has_bits: u32 // for every 32 fields
2478 /// - the bit is whether corresponding field has an value expression2494 /// - the bit is whether corresponding field has an value expression
2479 /// 4. fields: { // for every fields_len2495 /// 9. fields: { // for every fields_len
2480 /// field_name: u32,2496 /// field_name: u32,
2481 /// value: Ref, // if corresponding bit is set2497 /// value: Ref, // if corresponding bit is set
2482 /// }2498 /// }
2483 pub const EnumDecl = struct {2499 pub const EnumDecl = struct {
2484 /// Can be `Ref.none`.2500 pub const Small = packed struct {
2485 tag_type: Ref,2501 has_src_node: bool,
2486 body_len: u32,2502 has_tag_type: bool,
2487 fields_len: u32,2503 has_body_len: bool,
2488 decls_len: u32,2504 has_fields_len: bool,
2505 has_decls_len: bool,
2506 name_strategy: NameStrategy,
2507 nonexhaustive: bool,
2508 _: u8 = undefined,
2509 };
2489 };2510 };
24902511
2491 /// Trailing:2512 /// Trailing:
2492 /// 0. decl_bits: u32 // for every 8 decls2513 /// 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
2493 /// - sets of 4 bits:2519 /// - sets of 4 bits:
2494 /// 0b000X: whether corresponding decl is pub2520 /// 0b000X: whether corresponding decl is pub
2495 /// 0b00X0: whether corresponding decl is exported2521 /// 0b00X0: whether corresponding decl is exported
2496 /// 0b0X00: whether corresponding decl has an align expression2522 /// 0b0X00: whether corresponding decl has an align expression
2497 /// 0bX000: whether corresponding decl has a linksection expression2523 /// 0bX000: whether corresponding decl has a linksection expression
2498 /// 1. decl: { // for every decls_len2524 /// 6. decl: { // for every decls_len
2499 /// src_hash: [4]u32, // hash of source bytes2525 /// src_hash: [4]u32, // hash of source bytes
2500 /// line: u32, // line number of decl, relative to parent2526 /// line: u32, // line number of decl, relative to parent
2501 /// name: u32, // null terminated string index2527 /// name: u32, // null terminated string index
...@@ -2508,29 +2534,33 @@ pub const Inst = struct {...@@ -2508,29 +2534,33 @@ pub const Inst = struct {
2508 /// align: Ref, // if corresponding bit is set2534 /// align: Ref, // if corresponding bit is set
2509 /// link_section: Ref, // if corresponding bit is set2535 /// link_section: Ref, // if corresponding bit is set
2510 /// }2536 /// }
2511 /// 2. inst: Index // for every body_len2537 /// 7. inst: Index // for every body_len
2512 /// 3. has_bits: u32 // for every 8 fields2538 /// 8. has_bits: u32 // for every 8 fields
2513 /// - sets of 4 bits:2539 /// - sets of 4 bits:
2514 /// 0b000X: whether corresponding field has a type expression2540 /// 0b000X: whether corresponding field has a type expression
2515 /// 0b00X0: whether corresponding field has a align expression2541 /// 0b00X0: whether corresponding field has a align expression
2516 /// 0b0X00: whether corresponding field has a tag value expression2542 /// 0b0X00: whether corresponding field has a tag value expression
2517 /// 0bX000: unused(*)2543 /// 0bX000: unused
2518 /// * the first unused bit (the unused bit of the first field) is used2544 /// 9. fields: { // for every fields_len
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
2523 /// field_name: u32, // null terminated string index2545 /// field_name: u32, // null terminated string index
2524 /// field_type: Ref, // if corresponding bit is set2546 /// field_type: Ref, // if corresponding bit is set
2525 /// align: Ref, // if corresponding bit is set2547 /// align: Ref, // if corresponding bit is set
2526 /// tag_value: Ref, // if corresponding bit is set2548 /// tag_value: Ref, // if corresponding bit is set
2527 /// }2549 /// }
2528 pub const UnionDecl = struct {2550 pub const UnionDecl = struct {
2529 /// Can be `Ref.none`.2551 pub const Small = packed struct {
2530 tag_type: Ref,2552 has_src_node: bool,
2531 body_len: u32,2553 has_tag_type: bool,
2532 fields_len: u32,2554 has_body_len: bool,
2533 decls_len: u32,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 };
2534 };2564 };
25352565
2536 /// Trailing:2566 /// Trailing:
...@@ -2901,8 +2931,6 @@ const Writer = struct {...@@ -2901,8 +2931,6 @@ const Writer = struct {
2901 .field_type => try self.writeFieldType(stream, inst),2931 .field_type => try self.writeFieldType(stream, inst),
2902 .field_type_ref => try self.writeFieldTypeRef(stream, inst),2932 .field_type_ref => try self.writeFieldTypeRef(stream, inst),
29032933
2904 .error_set_decl => try self.writePlNodeErrorSetDecl(stream, inst),
2905
2906 .add,2934 .add,
2907 .addwrap,2935 .addwrap,
2908 .array_cat,2936 .array_cat,
...@@ -2980,21 +3008,13 @@ const Writer = struct {...@@ -2980,21 +3008,13 @@ const Writer = struct {
2980 .condbr_inline,3008 .condbr_inline,
2981 => try self.writePlNodeCondBr(stream, inst),3009 => try self.writePlNodeCondBr(stream, inst),
29823010
2983 .struct_decl,3011 .opaque_decl => try self.writeOpaqueDecl(stream, inst, .parent),
2984 .struct_decl_packed,3012 .opaque_decl_anon => try self.writeOpaqueDecl(stream, inst, .anon),
2985 .struct_decl_extern,3013 .opaque_decl_func => try self.writeOpaqueDecl(stream, inst, .func),
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),
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
2999 .switch_block => try self.writePlNodeSwitchBr(stream, inst, .none),3019 .switch_block => try self.writePlNodeSwitchBr(stream, inst, .none),
3000 .switch_block_else => try self.writePlNodeSwitchBr(stream, inst, .@"else"),3020 .switch_block_else => try self.writePlNodeSwitchBr(stream, inst, .@"else"),
...@@ -3080,6 +3100,10 @@ const Writer = struct {...@@ -3080,6 +3100,10 @@ const Writer = struct {
3080 .shl_with_overflow,3100 .shl_with_overflow,
3081 => try self.writeOverflowArithmetic(stream, extended),3101 => 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
3083 .alloc,3107 .alloc,
3084 .builtin_extern,3108 .builtin_extern,
3085 .c_undef,3109 .c_undef,
...@@ -3315,25 +3339,6 @@ const Writer = struct {...@@ -3315,25 +3339,6 @@ const Writer = struct {
3315 try self.writeSrc(stream, inst_data.src());3339 try self.writeSrc(stream, inst_data.src());
3316 }3340 }
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
3337 fn writeNodeMultiOp(self: *Writer, stream: anytype, extended: Inst.Extended.InstData) !void {3342 fn writeNodeMultiOp(self: *Writer, stream: anytype, extended: Inst.Extended.InstData) !void {
3338 const extra = self.code.extraData(Inst.NodeMultiOp, extended.operand);3343 const extra = self.code.extraData(Inst.NodeMultiOp, extended.operand);
3339 const src: LazySrcLoc = .{ .node_offset = extra.data.src_node };3344 const src: LazySrcLoc = .{ .node_offset = extra.data.src_node };
...@@ -3483,33 +3488,56 @@ const Writer = struct {...@@ -3483,33 +3488,56 @@ const Writer = struct {
3483 try self.writeSrc(stream, inst_data.src());3488 try self.writeSrc(stream, inst_data.src());
3484 }3489 }
34853490
3486 fn writeStructDecl(self: *Writer, stream: anytype, inst: Inst.Index) !void {3491 fn writeStructDecl(self: *Writer, stream: anytype, extended: Inst.Extended.InstData) !void {
3487 const inst_data = self.code.instructions.items(.data)[inst].pl_node;3492 const small = @bitCast(Inst.StructDecl.Small, extended.small);
3488 const extra = self.code.extraData(Inst.StructDecl, inst_data.payload_index);3493
3489 const fields_len = extra.data.fields_len;3494 var extra_index: usize = extended.operand;
3490 const decls_len = extra.data.decls_len;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
3494 if (decls_len == 0) {3524 if (decls_len == 0) {
3495 try stream.writeAll("{}, ");3525 try stream.writeAll("{}, ");
3496 extra_index = extra.end;
3497 } else {3526 } else {
3498 try stream.writeAll("{\n");3527 try stream.writeAll("{\n");
3499 self.indent += 2;3528 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);
3501 self.indent -= 2;3530 self.indent -= 2;
3502 try stream.writeByteNTimes(' ', self.indent);3531 try stream.writeByteNTimes(' ', self.indent);
3503 try stream.writeAll("}, ");3532 try stream.writeAll("}, ");
3504 }3533 }
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];
3507 extra_index += body.len;3536 extra_index += body.len;
35083537
3509 if (fields_len == 0) {3538 if (fields_len == 0) {
3510 assert(body.len == 0);3539 assert(body.len == 0);
3511 try stream.writeAll("{}, {}) ");3540 try stream.writeAll("{}, {})");
3512 extra_index = extra.end;
3513 } else {3541 } else {
3514 self.indent += 2;3542 self.indent += 2;
3515 if (body.len == 0) {3543 if (body.len == 0) {
...@@ -3575,41 +3603,70 @@ const Writer = struct {...@@ -3575,41 +3603,70 @@ const Writer = struct {
35753603
3576 self.indent -= 2;3604 self.indent -= 2;
3577 try stream.writeByteNTimes(' ', self.indent);3605 try stream.writeByteNTimes(' ', self.indent);
3578 try stream.writeAll("}) ");3606 try stream.writeAll("})");
3579 }3607 }
3580 try self.writeSrc(stream, inst_data.src());3608 try self.writeSrcNode(stream, src_node);
3581 }3609 }
35823610
3583 fn writeUnionDecl(self: *Writer, stream: anytype, inst: Inst.Index) !void {3611 fn writeUnionDecl(self: *Writer, stream: anytype, extended: Inst.Extended.InstData) !void {
3584 const inst_data = self.code.instructions.items(.data)[inst].pl_node;3612 const small = @bitCast(Inst.UnionDecl.Small, extended.small);
3585 const extra = self.code.extraData(Inst.UnionDecl, inst_data.payload_index);3613
3586 const fields_len = extra.data.fields_len;3614 var extra_index: usize = extended.operand;
3587 const decls_len = extra.data.decls_len;3615
3588 const tag_type_ref = extra.data.tag_type;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
3592 if (decls_len == 0) {3651 if (decls_len == 0) {
3593 try stream.writeAll("{}, ");3652 try stream.writeAll("{}, ");
3594 extra_index = extra.end;
3595 } else {3653 } else {
3596 try stream.writeAll("{\n");3654 try stream.writeAll("{\n");
3597 self.indent += 2;3655 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);
3599 self.indent -= 2;3657 self.indent -= 2;
3600 try stream.writeByteNTimes(' ', self.indent);3658 try stream.writeByteNTimes(' ', self.indent);
3601 try stream.writeAll("}, ");3659 try stream.writeAll("}, ");
3602 }3660 }
36033661
3604 assert(fields_len != 0);3662 assert(fields_len != 0);
3605 var first_has_auto_enum: ?bool = null;
36063663
3607 if (tag_type_ref != .none) {3664 if (tag_type_ref != .none) {
3608 try self.writeInstRef(stream, tag_type_ref);3665 try self.writeInstRef(stream, tag_type_ref);
3609 try stream.writeAll(", ");3666 try stream.writeAll(", ");
3610 }3667 }
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];
3613 extra_index += body.len;3670 extra_index += body.len;
36143671
3615 self.indent += 2;3672 self.indent += 2;
...@@ -3642,12 +3699,10 @@ const Writer = struct {...@@ -3642,12 +3699,10 @@ const Writer = struct {
3642 cur_bit_bag >>= 1;3699 cur_bit_bag >>= 1;
3643 const has_value = @truncate(u1, cur_bit_bag) != 0;3700 const has_value = @truncate(u1, cur_bit_bag) != 0;
3644 cur_bit_bag >>= 1;3701 cur_bit_bag >>= 1;
3645 const has_auto_enum = @truncate(u1, cur_bit_bag) != 0;3702 const unused = @truncate(u1, cur_bit_bag) != 0;
3646 cur_bit_bag >>= 1;3703 cur_bit_bag >>= 1;
36473704
3648 if (first_has_auto_enum == null) {3705 _ = unused;
3649 first_has_auto_enum = has_auto_enum;
3650 }
36513706
3652 const field_name = self.code.nullTerminatedString(self.code.extra[extra_index]);3707 const field_name = self.code.nullTerminatedString(self.code.extra[extra_index]);
3653 extra_index += 1;3708 extra_index += 1;
...@@ -3681,10 +3736,8 @@ const Writer = struct {...@@ -3681,10 +3736,8 @@ const Writer = struct {
36813736
3682 self.indent -= 2;3737 self.indent -= 2;
3683 try stream.writeByteNTimes(' ', self.indent);3738 try stream.writeByteNTimes(' ', self.indent);
3684 try stream.writeAll("}");3739 try stream.writeAll("})");
3685 try self.writeFlag(stream, ", autoenum", first_has_auto_enum.?);3740 try self.writeSrcNode(stream, src_node);
3686 try stream.writeAll(") ");
3687 try self.writeSrc(stream, inst_data.src());
3688 }3741 }
36893742
3690 fn writeDecls(self: *Writer, stream: anytype, decls_len: u32, extra_start: usize) !usize {3743 fn writeDecls(self: *Writer, stream: anytype, decls_len: u32, extra_start: usize) !usize {
...@@ -3776,22 +3829,49 @@ const Writer = struct {...@@ -3776,22 +3829,49 @@ const Writer = struct {
3776 return extra_index;3829 return extra_index;
3777 }3830 }
37783831
3779 fn writeEnumDecl(self: *Writer, stream: anytype, inst: Inst.Index) !void {3832 fn writeEnumDecl(self: *Writer, stream: anytype, extended: Inst.Extended.InstData) !void {
3780 const inst_data = self.code.instructions.items(.data)[inst].pl_node;3833 const small = @bitCast(Inst.EnumDecl.Small, extended.small);
3781 const extra = self.code.extraData(Inst.EnumDecl, inst_data.payload_index);3834 var extra_index: usize = extended.operand;
3782 const fields_len = extra.data.fields_len;3835
3783 const decls_len = extra.data.decls_len;3836 const src_node: ?i32 = if (small.has_src_node) blk: {
3784 const tag_type_ref = extra.data.tag_type;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
3788 if (decls_len == 0) {3869 if (decls_len == 0) {
3789 try stream.writeAll("{}, ");3870 try stream.writeAll("{}, ");
3790 extra_index = extra.end;
3791 } else {3871 } else {
3792 try stream.writeAll("{\n");3872 try stream.writeAll("{\n");
3793 self.indent += 2;3873 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);
3795 self.indent -= 2;3875 self.indent -= 2;
3796 try stream.writeByteNTimes(' ', self.indent);3876 try stream.writeByteNTimes(' ', self.indent);
3797 try stream.writeAll("}, ");3877 try stream.writeAll("}, ");
...@@ -3802,12 +3882,12 @@ const Writer = struct {...@@ -3802,12 +3882,12 @@ const Writer = struct {
3802 try stream.writeAll(", ");3882 try stream.writeAll(", ");
3803 }3883 }
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];
3806 extra_index += body.len;3886 extra_index += body.len;
38073887
3808 if (fields_len == 0) {3888 if (fields_len == 0) {
3809 assert(body.len == 0);3889 assert(body.len == 0);
3810 try stream.writeAll("{}, {}) ");3890 try stream.writeAll("{}, {})");
3811 } else {3891 } else {
3812 self.indent += 2;3892 self.indent += 2;
3813 if (body.len == 0) {3893 if (body.len == 0) {
...@@ -3851,16 +3931,23 @@ const Writer = struct {...@@ -3851,16 +3931,23 @@ const Writer = struct {
3851 }3931 }
3852 self.indent -= 2;3932 self.indent -= 2;
3853 try stream.writeByteNTimes(' ', self.indent);3933 try stream.writeByteNTimes(' ', self.indent);
3854 try stream.writeAll("}) ");3934 try stream.writeAll("})");
3855 }3935 }
3856 try self.writeSrc(stream, inst_data.src());3936 try self.writeSrcNode(stream, src_node);
3857 }3937 }
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 {
3860 const inst_data = self.code.instructions.items(.data)[inst].pl_node;3945 const inst_data = self.code.instructions.items(.data)[inst].pl_node;
3861 const extra = self.code.extraData(Inst.OpaqueDecl, inst_data.payload_index);3946 const extra = self.code.extraData(Inst.OpaqueDecl, inst_data.payload_index);
3862 const decls_len = extra.data.decls_len;3947 const decls_len = extra.data.decls_len;
38633948
3949 try stream.print("{s}, ", .{@tagName(name_strategy)});
3950
3864 if (decls_len == 0) {3951 if (decls_len == 0) {
3865 try stream.writeAll("}) ");3952 try stream.writeAll("}) ");
3866 } else {3953 } else {
...@@ -3874,6 +3961,32 @@ const Writer = struct {...@@ -3874,6 +3961,32 @@ const Writer = struct {
3874 try self.writeSrc(stream, inst_data.src());3961 try self.writeSrc(stream, inst_data.src());
3875 }3962 }
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
3877 fn writePlNodeSwitchBr(3990 fn writePlNodeSwitchBr(
3878 self: *Writer,3991 self: *Writer,
3879 stream: anytype,3992 stream: anytype,
...@@ -4337,6 +4450,13 @@ const Writer = struct {...@@ -4337,6 +4450,13 @@ const Writer = struct {
4337 });4450 });
4338 }4451 }
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
4340 fn writeBody(self: *Writer, stream: anytype, body: []const Inst.Index) !void {4460 fn writeBody(self: *Writer, stream: anytype, body: []const Inst.Index) !void {
4341 for (body) |inst| {4461 for (body) |inst| {
4342 try stream.writeByteNTimes(' ', self.indent);4462 try stream.writeByteNTimes(' ', self.indent);
...@@ -4389,75 +4509,86 @@ pub const DeclIterator = struct {...@@ -4389,75 +4509,86 @@ pub const DeclIterator = struct {
4389pub fn declIterator(zir: Zir, decl_inst: u32) DeclIterator {4509pub fn declIterator(zir: Zir, decl_inst: u32) DeclIterator {
4390 const tags = zir.instructions.items(.tag);4510 const tags = zir.instructions.items(.tag);
4391 const datas = zir.instructions.items(.data);4511 const datas = zir.instructions.items(.data);
4392 const decl_info: struct {4512 switch (tags[decl_inst]) {
4393 extra_index: usize,4513 .opaque_decl,
4394 decls_len: u32,4514 .opaque_decl_anon,
4395 } = switch (tags[decl_inst]) {4515 .opaque_decl_func,
4396 .struct_decl,4516 => {
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: {
4432 const inst_data = datas[decl_inst].pl_node;4517 const inst_data = datas[decl_inst].pl_node;
4433 const extra = zir.extraData(Inst.OpaqueDecl, inst_data.payload_index);4518 const extra = zir.extraData(Inst.OpaqueDecl, inst_data.payload_index);
4434 break :blk .{4519 return declIteratorInner(zir, extra.end, extra.data.decls_len);
4435 .extra_index = extra.end,
4436 .decls_len = extra.data.decls_len,
4437 };
4438 },4520 },
44394521
4440 // Functions are allowed and yield no iterations.4522 // Functions are allowed and yield no iterations.
4523 // There is one case matching this in the extended instruction set below.
4441 .func,4524 .func,
4442 .func_inferred,4525 .func_inferred,
4443 .extended, // assume also a function4526 => return declIteratorInner(zir, 0, 0),
4444 => .{
4445 .extra_index = 0,
4446 .decls_len = 0,
4447 },
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 },
4449 else => unreachable,4579 else => unreachable,
4450 };4580 }
44514581}
4452 const bit_bags_count = std.math.divCeil(usize, decl_info.decls_len, 8) catch unreachable;
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;
4454 return .{4585 return .{
4455 .zir = zir,4586 .zir = zir,
4456 .extra_index = decl_info.extra_index + bit_bags_count,4587 .extra_index = extra_index + bit_bags_count,
4457 .bit_bag_index = decl_info.extra_index,4588 .bit_bag_index = extra_index,
4458 .cur_bit_bag = undefined,4589 .cur_bit_bag = undefined,
4459 .decl_i = 0,4590 .decl_i = 0,
4460 .decls_len = decl_info.decls_len,4591 .decls_len = decls_len,
4461 };4592 };
4462}4593}
44634594
...@@ -4480,15 +4611,10 @@ fn findDeclsInner(...@@ -4480,15 +4611,10 @@ fn findDeclsInner(
44804611
4481 switch (tags[inst]) {4612 switch (tags[inst]) {
4482 // Decl instructions are interesting but have no body.4613 // Decl instructions are interesting but have no body.
4483 .struct_decl,4614 // TODO yes they do have a body actually. recurse over them just like block instructions.
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,
4491 .opaque_decl,4615 .opaque_decl,
4616 .opaque_decl_anon,
4617 .opaque_decl_func,
4492 => return list.append(inst),4618 => return list.append(inst),
44934619
4494 // Functions instructions are interesting and have a body.4620 // Functions instructions are interesting and have a body.
...@@ -4505,19 +4631,28 @@ fn findDeclsInner(...@@ -4505,19 +4631,28 @@ fn findDeclsInner(
4505 },4631 },
4506 .extended => {4632 .extended => {
4507 const extended = datas[inst].extended;4633 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);4654 else => return,
4513 const small = @bitCast(Inst.ExtendedFunc.Small, extended.small);4655 }
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);
4521 },4656 },
45224657
4523 // Block instructions, recurse over the bodies.4658 // Block instructions, recurse over the bodies.