authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-01-12 14:47:14+00:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-03-10 10:26:06+00:00
log5e8397d5e03269d8a39efb22605ea20102848084
treec3f0fffeff44be63f7c6691737ad0cd6510e6c76
parentcfe5c88ad6081e284d0caf36cf8d7e80fe39b676
signaturelock-open Commit is signed but in an unrecognized format.

Zir: rework container type declarations

Only AstGen and print_zir currently support the new representation, so attempting to build the compiler will emit (many) compile errors.

3 files changed, 1204 insertions(+), 1925 deletions(-)

lib/std/zig/AstGen.zig+530-1122
......@@ -3975,81 +3975,67 @@ fn arrayTypeSentinel(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.
39753975 return rvalue(gz, ri, result, node);
39763976}
39773977
3978const WipMembers = struct {
3979 payload: *ArrayList(u32),
3980 payload_top: usize,
3981 field_bits_start: u32,
3982 fields_start: u32,
3983 fields_end: u32,
3984 decl_index: u32 = 0,
3985 field_index: u32 = 0,
3986
3987 const Self = @This();
3988
3989 fn init(gpa: Allocator, payload: *ArrayList(u32), decl_count: u32, field_count: u32, comptime bits_per_field: u32, comptime max_field_size: u32) Allocator.Error!Self {
3990 const payload_top: u32 = @intCast(payload.items.len);
3991 const field_bits_start = payload_top + decl_count;
3992 const fields_start = field_bits_start + if (bits_per_field > 0) blk: {
3993 const fields_per_u32 = 32 / bits_per_field;
3994 break :blk (field_count + fields_per_u32 - 1) / fields_per_u32;
3995 } else 0;
3996 const payload_end = fields_start + field_count * max_field_size;
3997 try payload.resize(gpa, payload_end);
3978const Scratch = struct {
3979 astgen: *AstGen,
3980 scratch_top: u32,
3981 fn init(astgen: *AstGen) Scratch {
39983982 return .{
3999 .payload = payload,
4000 .payload_top = payload_top,
4001 .field_bits_start = field_bits_start,
4002 .fields_start = fields_start,
4003 .fields_end = fields_start,
3983 .astgen = astgen,
3984 .scratch_top = @intCast(astgen.scratch.items.len),
40043985 };
40053986 }
4006
4007 fn nextDecl(self: *Self, decl_inst: Zir.Inst.Index) void {
4008 self.payload.items[self.payload_top + self.decl_index] = @intFromEnum(decl_inst);
4009 self.decl_index += 1;
3987 fn reset(s: *Scratch) void {
3988 s.astgen.scratch.shrinkRetainingCapacity(s.scratch_top);
3989 s.* = undefined;
40103990 }
4011
4012 fn nextField(self: *Self, comptime bits_per_field: u32, bits: [bits_per_field]bool) void {
4013 const fields_per_u32 = 32 / bits_per_field;
4014 const index = self.field_bits_start + self.field_index / fields_per_u32;
4015 assert(index < self.fields_start);
4016 var bit_bag: u32 = if (self.field_index % fields_per_u32 == 0) 0 else self.payload.items[index];
4017 bit_bag >>= bits_per_field;
4018 comptime var i = 0;
4019 inline while (i < bits_per_field) : (i += 1) {
4020 bit_bag |= @as(u32, @intFromBool(bits[i])) << (32 - bits_per_field + i);
4021 }
4022 self.payload.items[index] = bit_bag;
4023 self.field_index += 1;
3991 fn addSlice(s: *Scratch, len: u32) Allocator.Error!Slice {
3992 const start: u32 = @intCast(s.astgen.scratch.items.len);
3993 try s.astgen.scratch.resize(s.astgen.gpa, start + len);
3994 return .{ .start = start, .len = len };
40243995 }
4025
4026 fn appendToField(self: *Self, data: u32) void {
4027 assert(self.fields_end < self.payload.items.len);
4028 self.payload.items[self.fields_end] = data;
4029 self.fields_end += 1;
3996 fn addOptionalSlice(s: *Scratch, present: bool, len: u32) Allocator.Error!?Slice {
3997 if (!present) return null;
3998 return try addSlice(s, len);
40303999 }
4031
4032 fn finishBits(self: *Self, comptime bits_per_field: u32) void {
4033 if (bits_per_field > 0) {
4034 const fields_per_u32 = 32 / bits_per_field;
4035 const empty_field_slots = fields_per_u32 - (self.field_index % fields_per_u32);
4036 if (self.field_index > 0 and empty_field_slots < fields_per_u32) {
4037 const index = self.field_bits_start + self.field_index / fields_per_u32;
4038 self.payload.items[index] >>= @intCast(empty_field_slots * bits_per_field);
4039 }
4040 }
4000 fn appendBodyWithFixups(s: *Scratch, body: []const Zir.Inst.Index) Allocator.Error!u32 {
4001 const len = countBodyLenAfterFixups(s.astgen, body);
4002 try s.astgen.scratch.ensureUnusedCapacity(s.astgen.gpa, len);
4003 appendBodyWithFixupsArrayList(s.astgen, &s.astgen.scratch, body);
4004 return len;
40414005 }
4042
4043 fn declsSlice(self: *Self) []u32 {
4044 return self.payload.items[self.payload_top..][0..self.decl_index];
4006 /// Returns the slice containing all data added to this `Scratch`.
4007 fn all(s: *Scratch) Slice {
4008 const len = s.astgen.scratch.items.len - s.scratch_top;
4009 return .{ .start = s.scratch_top, .len = @intCast(len) };
40454010 }
4011 const Slice = struct {
4012 start: u32,
4013 len: u32,
4014 fn get(s: Slice, astgen: *AstGen) []u32 {
4015 return astgen.scratch.items[s.start..][0..s.len];
4016 }
4017 };
4018};
40464019
4047 fn fieldsSlice(self: *Self) []u32 {
4048 return self.payload.items[self.field_bits_start..self.fields_end];
4049 }
4020const WipDecls = struct {
4021 astgen: *AstGen,
4022 slice: Scratch.Slice,
4023 index: u32,
40504024
4051 fn deinit(self: *Self) void {
4052 self.payload.items.len = self.payload_top;
4025 fn init(scratch: *Scratch, decls_len: u32) Allocator.Error!WipDecls {
4026 return .{
4027 .astgen = scratch.astgen,
4028 .slice = try scratch.addSlice(decls_len),
4029 .index = 0,
4030 };
4031 }
4032 fn finish(wip: *WipDecls) void {
4033 assert(wip.index == wip.slice.len);
4034 wip.* = undefined;
4035 }
4036 fn nextDecl(wip: *WipDecls, decl_inst: Zir.Inst.Index) void {
4037 wip.slice.get(wip.astgen)[wip.index] = @intFromEnum(decl_inst);
4038 wip.index += 1;
40534039 }
40544040};
40554041
......@@ -4057,7 +4043,7 @@ fn fnDecl(
40574043 astgen: *AstGen,
40584044 gz: *GenZir,
40594045 scope: *Scope,
4060 wip_members: *WipMembers,
4046 wip_decls: *WipDecls,
40614047 decl_node: Ast.Node.Index,
40624048 body_node: Ast.Node.OptionalIndex,
40634049 fn_proto: Ast.full.FnProto,
......@@ -4133,7 +4119,7 @@ fn fnDecl(
41334119 assert(!is_extern); // validated by parser (TODO why???)
41344120 }
41354121
4136 wip_members.nextDecl(decl_inst);
4122 wip_decls.nextDecl(decl_inst);
41374123
41384124 var type_gz: GenZir = .{
41394125 .is_comptime = true,
......@@ -4488,7 +4474,7 @@ fn globalVarDecl(
44884474 astgen: *AstGen,
44894475 gz: *GenZir,
44904476 scope: *Scope,
4491 wip_members: *WipMembers,
4477 wip_decls: *WipDecls,
44924478 node: Ast.Node.Index,
44934479 var_decl: Ast.full.VarDecl,
44944480) InnerError!void {
......@@ -4533,7 +4519,7 @@ fn globalVarDecl(
45334519 const decl_column = astgen.source_column;
45344520
45354521 const decl_inst = try gz.makeDeclaration(node);
4536 wip_members.nextDecl(decl_inst);
4522 wip_decls.nextDecl(decl_inst);
45374523
45384524 if (var_decl.ast.init_node.unwrap()) |init_node| {
45394525 if (is_extern) {
......@@ -4635,7 +4621,7 @@ fn comptimeDecl(
46354621 astgen: *AstGen,
46364622 gz: *GenZir,
46374623 scope: *Scope,
4638 wip_members: *WipMembers,
4624 wip_decls: *WipDecls,
46394625 node: Ast.Node.Index,
46404626) InnerError!void {
46414627 const tree = astgen.tree;
......@@ -4650,7 +4636,7 @@ fn comptimeDecl(
46504636 // Up top so the ZIR instruction index marks the start range of this
46514637 // top-level declaration.
46524638 const decl_inst = try gz.makeDeclaration(node);
4653 wip_members.nextDecl(decl_inst);
4639 wip_decls.nextDecl(decl_inst);
46544640 astgen.advanceSourceCursorToNode(node);
46554641
46564642 // This is just needed for the `setDeclaration` call.
......@@ -4698,7 +4684,7 @@ fn testDecl(
46984684 astgen: *AstGen,
46994685 gz: *GenZir,
47004686 scope: *Scope,
4701 wip_members: *WipMembers,
4687 wip_decls: *WipDecls,
47024688 node: Ast.Node.Index,
47034689) InnerError!void {
47044690 const tree = astgen.tree;
......@@ -4714,7 +4700,7 @@ fn testDecl(
47144700 // top-level declaration.
47154701 const decl_inst = try gz.makeDeclaration(node);
47164702
4717 wip_members.nextDecl(decl_inst);
4703 wip_decls.nextDecl(decl_inst);
47184704 astgen.advanceSourceCursorToNode(node);
47194705
47204706 // This is just needed for the `setDeclaration` call.
......@@ -4914,7 +4900,7 @@ fn structDeclInner(
49144900 node: Ast.Node.Index,
49154901 container_decl: Ast.full.ContainerDecl,
49164902 layout: std.builtin.Type.ContainerLayout,
4917 backing_int_node: Ast.Node.OptionalIndex,
4903 maybe_backing_int_node: Ast.Node.OptionalIndex,
49184904 name_strat: Zir.Inst.NameStrategy,
49194905) InnerError!Zir.Inst.Ref {
49204906 const astgen = gz.astgen;
......@@ -4930,27 +4916,39 @@ fn structDeclInner(
49304916 if (node == .root) {
49314917 return astgen.failNode(tuple_field_node, "file cannot be a tuple", .{});
49324918 } else {
4933 return tupleDecl(gz, scope, node, container_decl, layout, backing_int_node);
4919 return tupleDecl(gz, scope, node, container_decl, layout, maybe_backing_int_node);
49344920 }
49354921 }
49364922
4923 astgen.advanceSourceCursorToNode(node);
4924
4925 const backing_int_type_ref: Zir.Inst.Ref = ty: {
4926 const backing_int_node = maybe_backing_int_node.unwrap() orelse break :ty .none;
4927 if (layout != .@"packed") return astgen.failNode(
4928 backing_int_node,
4929 "non-packed struct does not support backing integer type",
4930 .{},
4931 );
4932 break :ty try typeExpr(gz, scope, backing_int_node);
4933 };
4934
49374935 const decl_inst = try gz.reserveInstructionIndex();
49384936
4939 if (container_decl.ast.members.len == 0 and backing_int_node == .none) {
4937 if (container_decl.ast.members.len == 0 and backing_int_type_ref == .none) {
49404938 try gz.setStruct(decl_inst, .{
49414939 .src_node = node,
4940 .name_strat = name_strat,
49424941 .layout = layout,
4943 .captures_len = 0,
4944 .fields_len = 0,
4942 .backing_int_type = .none,
49454943 .decls_len = 0,
4946 .has_backing_int = false,
4947 .known_non_opv = false,
4948 .known_comptime_only = false,
4944 .fields_len = 0,
4945 .any_field_aligns = false,
4946 .any_field_defaults = false,
49494947 .any_comptime_fields = false,
4950 .any_default_inits = false,
4951 .any_aligned_fields = false,
4952 .fields_hash = std.zig.hashSrc(@tagName(layout)),
4953 .name_strat = name_strat,
4948 .fields_hash = @splat(0),
4949 .captures = &.{},
4950 .capture_names = &.{},
4951 .remaining = &.{},
49544952 });
49554953 return decl_inst.toRef();
49564954 }
......@@ -4967,7 +4965,6 @@ fn structDeclInner(
49674965 // The struct_decl instruction introduces a scope in which the decls of the struct
49684966 // are in scope, so that field types, alignments, and default value expressions
49694967 // can refer to decls within the struct itself.
4970 astgen.advanceSourceCursorToNode(node);
49714968 var block_scope: GenZir = .{
49724969 .parent = &namespace.base,
49734970 .decl_node_index = node,
......@@ -4979,197 +4976,118 @@ fn structDeclInner(
49794976 };
49804977 defer block_scope.unstack();
49814978
4982 const scratch_top = astgen.scratch.items.len;
4983 defer astgen.scratch.items.len = scratch_top;
4984
4985 var backing_int_body_len: usize = 0;
4986 const backing_int_ref: Zir.Inst.Ref = blk: {
4987 if (backing_int_node.unwrap()) |arg| {
4988 if (layout != .@"packed") {
4989 return astgen.failNode(arg, "non-packed struct does not support backing integer type", .{});
4990 } else {
4991 const backing_int_ref = try typeExpr(&block_scope, &namespace.base, arg);
4992 if (!block_scope.isEmpty()) {
4993 if (!block_scope.endsWithNoReturn()) {
4994 _ = try block_scope.addBreak(.break_inline, decl_inst, backing_int_ref);
4995 }
4996
4997 const body = block_scope.instructionsSlice();
4998 const old_scratch_len = astgen.scratch.items.len;
4999 try astgen.scratch.ensureUnusedCapacity(gpa, countBodyLenAfterFixups(astgen, body));
5000 appendBodyWithFixupsArrayList(astgen, &astgen.scratch, body);
5001 backing_int_body_len = astgen.scratch.items.len - old_scratch_len;
5002 block_scope.instructions.items.len = block_scope.instructions_top;
5003 }
5004 break :blk backing_int_ref;
5005 }
5006 } else {
5007 break :blk .none;
5008 }
5009 };
4979 const scan_result = try astgen.scanContainer(&namespace, container_decl.ast.members, .@"struct");
50104980
5011 const decl_count = try astgen.scanContainer(&namespace, container_decl.ast.members, .@"struct");
5012 const field_count: u32 = @intCast(container_decl.ast.members.len - decl_count);
4981 var scratch: Scratch = .init(astgen);
4982 defer scratch.reset();
50134983
5014 const bits_per_field = 4;
5015 const max_field_size = 5;
5016 var wip_members = try WipMembers.init(gpa, &astgen.scratch, decl_count, field_count, bits_per_field, max_field_size);
5017 defer wip_members.deinit();
5018
5019 // We will use the scratch buffer, starting here, for the bodies:
5020 // bodies: { // for every fields_len
5021 // field_type_body_inst: Inst, // for each field_type_body_len
5022 // align_body_inst: Inst, // for each align_body_len
5023 // init_body_inst: Inst, // for each init_body_len
5024 // }
5025 // Note that the scratch buffer is simultaneously being used by WipMembers, however
5026 // it will not access any elements beyond this point in the ArrayList. It also
5027 // accesses via the ArrayList items field so it can handle the scratch buffer being
5028 // reallocated.
5029 // No defer needed here because it is handled by `wip_members.deinit()` above.
5030 const bodies_start = astgen.scratch.items.len;
4984 // Replicate the structure of the ZIR trailing data in `scratch`
4985 var wip_decls: WipDecls = try .init(&scratch, scan_result.decls_len);
4986 const field_names = try scratch.addSlice(scan_result.fields_len);
4987 const field_type_body_lens = try scratch.addSlice(scan_result.fields_len);
4988 const field_align_body_lens = try scratch.addOptionalSlice(scan_result.any_field_aligns, scan_result.fields_len);
4989 const field_default_body_lens = try scratch.addOptionalSlice(scan_result.any_field_values, scan_result.fields_len);
4990 const field_comptime_bits = try scratch.addOptionalSlice(
4991 scan_result.any_comptime_fields,
4992 std.math.divCeil(u32, scan_result.fields_len, 32) catch unreachable,
4993 );
4994 if (field_comptime_bits) |bits| @memset(bits.get(astgen), 0);
50314995
50324996 const old_hasher = astgen.src_hasher;
50334997 defer astgen.src_hasher = old_hasher;
5034 astgen.src_hasher = std.zig.SrcHasher.init(.{});
5035 astgen.src_hasher.update(@tagName(layout));
5036 if (backing_int_node.unwrap()) |arg| {
5037 astgen.src_hasher.update(tree.getNodeSource(arg));
5038 }
4998 astgen.src_hasher = .init(.{});
50394999
5040 var known_non_opv = false;
5041 var known_comptime_only = false;
5042 var any_comptime_fields = false;
5043 var any_aligned_fields = false;
5044 var any_default_inits = false;
5000 var next_field_idx: u32 = 0;
50455001 for (container_decl.ast.members) |member_node| {
5046 var member = switch (try containerMember(&block_scope, &namespace.base, &wip_members, member_node)) {
5002 var member = switch (try containerMember(&block_scope, &namespace.base, &wip_decls, member_node)) {
50475003 .decl => continue,
50485004 .field => |field| field,
50495005 };
5006 const field_idx = next_field_idx;
5007 next_field_idx += 1;
50505008
50515009 astgen.src_hasher.update(tree.getNodeSource(member_node));
50525010
5053 const field_name = try astgen.identAsString(member.ast.main_token);
50545011 member.convertToNonTupleLike(astgen.tree);
50555012 assert(!member.ast.tuple_like);
5056 wip_members.appendToField(@intFromEnum(field_name));
5057
5058 const type_expr = member.ast.type_expr.unwrap() orelse {
5059 return astgen.failTok(member.ast.main_token, "struct field missing type", .{});
5060 };
5061
5062 const field_type = try typeExpr(&block_scope, &namespace.base, type_expr);
5063 const have_type_body = !block_scope.isEmpty();
5064 const have_align = member.ast.align_expr != .none;
5065 const have_value = member.ast.value_expr != .none;
5066 const is_comptime = member.comptime_token != null;
50675013
5068 if (is_comptime) {
5069 switch (layout) {
5070 .@"packed", .@"extern" => return astgen.failTok(member.comptime_token.?, "{s} struct fields cannot be marked comptime", .{@tagName(layout)}),
5071 .auto => any_comptime_fields = true,
5072 }
5073 } else {
5074 known_non_opv = known_non_opv or
5075 nodeImpliesMoreThanOnePossibleValue(tree, type_expr);
5076 known_comptime_only = known_comptime_only or
5077 nodeImpliesComptimeOnly(tree, type_expr);
5078 }
5079 wip_members.nextField(bits_per_field, .{ have_align, have_value, is_comptime, have_type_body });
5014 field_names.get(astgen)[field_idx] = @intFromEnum(try astgen.identAsString(member.ast.main_token));
50805015
5081 if (have_type_body) {
5016 {
5017 const type_node = member.ast.type_expr.unwrap() orelse {
5018 return astgen.failTok(member.ast.main_token, "struct field missing type", .{});
5019 };
5020 const type_ref = try typeExpr(&block_scope, &namespace.base, type_node);
50825021 if (!block_scope.endsWithNoReturn()) {
5083 _ = try block_scope.addBreak(.break_inline, decl_inst, field_type);
5022 _ = try block_scope.addBreak(.break_inline, decl_inst, type_ref);
50845023 }
5085 const body = block_scope.instructionsSlice();
5086 const old_scratch_len = astgen.scratch.items.len;
5087 try astgen.scratch.ensureUnusedCapacity(gpa, countBodyLenAfterFixups(astgen, body));
5088 appendBodyWithFixupsArrayList(astgen, &astgen.scratch, body);
5089 wip_members.appendToField(@intCast(astgen.scratch.items.len - old_scratch_len));
5024 const body_len = try scratch.appendBodyWithFixups(block_scope.instructionsSlice());
5025 field_type_body_lens.get(astgen)[field_idx] = body_len;
50905026 block_scope.instructions.items.len = block_scope.instructions_top;
5091 } else {
5092 wip_members.appendToField(@intFromEnum(field_type));
50935027 }
50945028
5095 if (member.ast.align_expr.unwrap()) |align_expr| {
5029 if (member.ast.align_expr.unwrap()) |align_node| {
50965030 if (layout == .@"packed") {
5097 return astgen.failNode(align_expr, "unable to override alignment of packed struct fields", .{});
5031 return astgen.failNode(align_node, "unable to override alignment of packed struct fields", .{});
50985032 }
5099 any_aligned_fields = true;
5100 const align_ref = try expr(&block_scope, &namespace.base, coerced_align_ri, align_expr);
5033 const align_ref = try expr(&block_scope, &namespace.base, coerced_align_ri, align_node);
51015034 if (!block_scope.endsWithNoReturn()) {
51025035 _ = try block_scope.addBreak(.break_inline, decl_inst, align_ref);
51035036 }
5104 const body = block_scope.instructionsSlice();
5105 const old_scratch_len = astgen.scratch.items.len;
5106 try astgen.scratch.ensureUnusedCapacity(gpa, countBodyLenAfterFixups(astgen, body));
5107 appendBodyWithFixupsArrayList(astgen, &astgen.scratch, body);
5108 wip_members.appendToField(@intCast(astgen.scratch.items.len - old_scratch_len));
5037 const body_len = try scratch.appendBodyWithFixups(block_scope.instructionsSlice());
5038 field_align_body_lens.?.get(astgen)[field_idx] = body_len;
51095039 block_scope.instructions.items.len = block_scope.instructions_top;
5040 } else if (field_align_body_lens) |lens| {
5041 lens.get(astgen)[field_idx] = 0;
51105042 }
51115043
5112 if (member.ast.value_expr.unwrap()) |value_expr| {
5113 any_default_inits = true;
5114
5115 // The decl_inst is used as here so that we can easily reconstruct a mapping
5116 // between it and the field type when the fields inits are analyzed.
5117 const ri: ResultInfo = .{ .rl = if (field_type == .none) .none else .{ .coerced_ty = decl_inst.toRef() } };
5118
5119 const default_inst = try expr(&block_scope, &namespace.base, ri, value_expr);
5044 if (member.ast.value_expr.unwrap()) |default_node| {
5045 const ri: ResultInfo = .{ .rl = .{ .coerced_ty = decl_inst.toRef() } };
5046 const default_ref = try expr(&block_scope, &namespace.base, ri, default_node);
51205047 if (!block_scope.endsWithNoReturn()) {
5121 _ = try block_scope.addBreak(.break_inline, decl_inst, default_inst);
5048 _ = try block_scope.addBreak(.break_inline, decl_inst, default_ref);
51225049 }
5123 const body = block_scope.instructionsSlice();
5124 const old_scratch_len = astgen.scratch.items.len;
5125 try astgen.scratch.ensureUnusedCapacity(gpa, countBodyLenAfterFixups(astgen, body));
5126 appendBodyWithFixupsArrayList(astgen, &astgen.scratch, body);
5127 wip_members.appendToField(@intCast(astgen.scratch.items.len - old_scratch_len));
5050 const body_len = try scratch.appendBodyWithFixups(block_scope.instructionsSlice());
5051 field_default_body_lens.?.get(astgen)[field_idx] = body_len;
51285052 block_scope.instructions.items.len = block_scope.instructions_top;
5129 } else if (member.comptime_token) |comptime_token| {
5130 return astgen.failTok(comptime_token, "comptime field without default initialization value", .{});
5053 } else if (field_default_body_lens) |lens| {
5054 lens.get(astgen)[field_idx] = 0;
5055 }
5056
5057 if (member.comptime_token) |comptime_token| {
5058 switch (layout) {
5059 .@"packed", .@"extern" => return astgen.failTok(comptime_token, "{s} struct fields cannot be marked comptime", .{@tagName(layout)}),
5060 .auto => {},
5061 }
5062 if (member.ast.value_expr == .none) {
5063 return astgen.failTok(comptime_token, "comptime field without default initialization value", .{});
5064 }
5065 const mask = @as(u32, 1) << @intCast(field_idx % 32);
5066 field_comptime_bits.?.get(astgen)[field_idx / 32] |= mask;
51315067 }
51325068 }
5069 assert(next_field_idx == scan_result.fields_len);
5070 wip_decls.finish();
51335071
51345072 var fields_hash: std.zig.SrcHash = undefined;
51355073 astgen.src_hasher.final(&fields_hash);
51365074
51375075 try gz.setStruct(decl_inst, .{
51385076 .src_node = node,
5077 .name_strat = name_strat,
51395078 .layout = layout,
5140 .captures_len = @intCast(namespace.captures.count()),
5141 .fields_len = field_count,
5142 .decls_len = decl_count,
5143 .has_backing_int = backing_int_ref != .none,
5144 .known_non_opv = known_non_opv,
5145 .known_comptime_only = known_comptime_only,
5146 .any_comptime_fields = any_comptime_fields,
5147 .any_default_inits = any_default_inits,
5148 .any_aligned_fields = any_aligned_fields,
5079 .backing_int_type = backing_int_type_ref,
5080 .decls_len = scan_result.decls_len,
5081 .fields_len = scan_result.fields_len,
5082 .any_field_aligns = scan_result.any_field_aligns,
5083 .any_field_defaults = scan_result.any_field_values,
5084 .any_comptime_fields = scan_result.any_comptime_fields,
51495085 .fields_hash = fields_hash,
5150 .name_strat = name_strat,
5086 .captures = namespace.captures.keys(),
5087 .capture_names = namespace.captures.values(),
5088 .remaining = scratch.all().get(astgen),
51515089 });
51525090
5153 wip_members.finishBits(bits_per_field);
5154 const decls_slice = wip_members.declsSlice();
5155 const fields_slice = wip_members.fieldsSlice();
5156 const bodies_slice = astgen.scratch.items[bodies_start..];
5157 try astgen.extra.ensureUnusedCapacity(gpa, backing_int_body_len + 2 +
5158 decls_slice.len + namespace.captures.count() * 2 + fields_slice.len + bodies_slice.len);
5159 astgen.extra.appendSliceAssumeCapacity(@ptrCast(namespace.captures.keys()));
5160 astgen.extra.appendSliceAssumeCapacity(@ptrCast(namespace.captures.values()));
5161 if (backing_int_ref != .none) {
5162 astgen.extra.appendAssumeCapacity(@intCast(backing_int_body_len));
5163 if (backing_int_body_len == 0) {
5164 astgen.extra.appendAssumeCapacity(@intFromEnum(backing_int_ref));
5165 } else {
5166 astgen.extra.appendSliceAssumeCapacity(astgen.scratch.items[scratch_top..][0..backing_int_body_len]);
5167 }
5168 }
5169 astgen.extra.appendSliceAssumeCapacity(decls_slice);
5170 astgen.extra.appendSliceAssumeCapacity(fields_slice);
5171 astgen.extra.appendSliceAssumeCapacity(bodies_slice);
5172
51735091 block_scope.unstack();
51745092 return decl_inst.toRef();
51755093}
......@@ -5281,11 +5199,34 @@ fn unionDeclInner(
52815199 auto_enum_tok: ?Ast.TokenIndex,
52825200 name_strat: Zir.Inst.NameStrategy,
52835201) InnerError!Zir.Inst.Ref {
5284 const decl_inst = try gz.reserveInstructionIndex();
5285
52865202 const astgen = gz.astgen;
52875203 const gpa = astgen.gpa;
52885204
5205 const explicit_int_or_enum_tag = switch (layout) {
5206 .auto => opt_arg_node != .none,
5207 .@"extern" => if (opt_arg_node.unwrap()) |arg_node| {
5208 return astgen.failNode(arg_node, "{s} union does not support enum tag type", .{@tagName(layout)});
5209 } else false,
5210 .@"packed" => false,
5211 };
5212
5213 if (auto_enum_tok) |t| {
5214 if (layout != .auto) {
5215 return astgen.failTok(t, "{s} union does not support enum tag type", .{@tagName(layout)});
5216 }
5217 }
5218
5219 const is_tagged = explicit_int_or_enum_tag or auto_enum_tok != null;
5220
5221 astgen.advanceSourceCursorToNode(node);
5222
5223 const arg_type_ref: Zir.Inst.Ref = ref: {
5224 const arg_node = opt_arg_node.unwrap() orelse break :ref .none;
5225 break :ref try typeExpr(gz, scope, arg_node);
5226 };
5227
5228 const decl_inst = try gz.reserveInstructionIndex();
5229
52895230 var namespace: Scope.Namespace = .{
52905231 .parent = scope,
52915232 .node = node,
......@@ -5298,7 +5239,6 @@ fn unionDeclInner(
52985239 // The union_decl instruction introduces a scope in which the decls of the union
52995240 // are in scope, so that field types, alignments, and default value expressions
53005241 // can refer to decls within the union itself.
5301 astgen.advanceSourceCursorToNode(node);
53025242 var block_scope: GenZir = .{
53035243 .parent = &namespace.base,
53045244 .decl_node_index = node,
......@@ -5310,42 +5250,31 @@ fn unionDeclInner(
53105250 };
53115251 defer block_scope.unstack();
53125252
5313 const decl_count = try astgen.scanContainer(&namespace, members, .@"union");
5314 const field_count: u32 = @intCast(members.len - decl_count);
5315
5316 if (layout != .auto and (auto_enum_tok != null or opt_arg_node != .none)) {
5317 if (opt_arg_node.unwrap()) |arg_node| {
5318 return astgen.failNode(arg_node, "{s} union does not support enum tag type", .{@tagName(layout)});
5319 } else {
5320 return astgen.failTok(auto_enum_tok.?, "{s} union does not support enum tag type", .{@tagName(layout)});
5321 }
5322 }
5253 const scan_result = try astgen.scanContainer(&namespace, members, .@"union");
53235254
5324 const arg_inst: Zir.Inst.Ref = if (opt_arg_node.unwrap()) |arg_node|
5325 try typeExpr(&block_scope, &namespace.base, arg_node)
5326 else
5327 .none;
5255 var scratch: Scratch = .init(astgen);
5256 defer scratch.reset();
53285257
5329 const bits_per_field = 4;
5330 const max_field_size = 4;
5331 var any_aligned_fields = false;
5332 var wip_members = try WipMembers.init(gpa, &astgen.scratch, decl_count, field_count, bits_per_field, max_field_size);
5333 defer wip_members.deinit();
5258 // Replicate the structure of the ZIR trailing data in `scratch`
5259 var wip_decls: WipDecls = try .init(&scratch, scan_result.decls_len);
5260 const field_names = try scratch.addSlice(scan_result.fields_len);
5261 const field_type_body_lens = try scratch.addSlice(scan_result.fields_len);
5262 const field_align_body_lens = try scratch.addOptionalSlice(scan_result.any_field_aligns, scan_result.fields_len);
5263 const field_value_body_lens = try scratch.addOptionalSlice(scan_result.any_field_values, scan_result.fields_len);
53345264
53355265 const old_hasher = astgen.src_hasher;
53365266 defer astgen.src_hasher = old_hasher;
5337 astgen.src_hasher = std.zig.SrcHasher.init(.{});
5338 astgen.src_hasher.update(@tagName(layout));
5339 astgen.src_hasher.update(&.{@intFromBool(auto_enum_tok != null)});
5340 if (opt_arg_node.unwrap()) |arg_node| {
5341 astgen.src_hasher.update(astgen.tree.getNodeSource(arg_node));
5342 }
5267 astgen.src_hasher = .init(.{});
53435268
5269 var next_field_idx: u32 = 0;
53445270 for (members) |member_node| {
5345 var member = switch (try containerMember(&block_scope, &namespace.base, &wip_members, member_node)) {
5271 var member = switch (try containerMember(&block_scope, &namespace.base, &wip_decls, member_node)) {
53465272 .decl => continue,
53475273 .field => |field| field,
53485274 };
5275 const field_idx = next_field_idx;
5276 next_field_idx += 1;
5277
53495278 astgen.src_hasher.update(astgen.tree.getNodeSource(member_node));
53505279 member.convertToNonTupleLike(astgen.tree);
53515280 if (member.ast.tuple_like) {
......@@ -5355,97 +5284,91 @@ fn unionDeclInner(
53555284 return astgen.failTok(comptime_token, "union fields cannot be marked comptime", .{});
53565285 }
53575286
5358 const field_name = try astgen.identAsString(member.ast.main_token);
5359 wip_members.appendToField(@intFromEnum(field_name));
5360
5361 const have_type = member.ast.type_expr != .none;
5362 const have_align = member.ast.align_expr != .none;
5363 const have_value = member.ast.value_expr != .none;
5364 const unused = false;
5365 wip_members.nextField(bits_per_field, .{ have_type, have_align, have_value, unused });
5287 field_names.get(astgen)[field_idx] = @intFromEnum(try astgen.identAsString(member.ast.main_token));
53665288
5367 if (member.ast.type_expr.unwrap()) |type_expr| {
5368 const field_type = try typeExpr(&block_scope, &namespace.base, type_expr);
5369 wip_members.appendToField(@intFromEnum(field_type));
5370 } else if (arg_inst == .none and auto_enum_tok == null) {
5289 if (member.ast.type_expr.unwrap()) |type_node| {
5290 const type_ref = try typeExpr(&block_scope, &namespace.base, type_node);
5291 if (!block_scope.endsWithNoReturn()) {
5292 _ = try block_scope.addBreak(.break_inline, decl_inst, type_ref);
5293 }
5294 const body_len = try scratch.appendBodyWithFixups(block_scope.instructionsSlice());
5295 field_type_body_lens.get(astgen)[field_idx] = body_len;
5296 block_scope.instructions.items.len = block_scope.instructions_top;
5297 } else if (!is_tagged) {
53715298 return astgen.failNode(member_node, "union field missing type", .{});
5299 } else {
5300 field_type_body_lens.get(astgen)[field_idx] = 0;
53725301 }
5373 if (member.ast.align_expr.unwrap()) |align_expr| {
5302
5303 if (member.ast.align_expr.unwrap()) |align_node| {
53745304 if (layout == .@"packed") {
5375 return astgen.failNode(align_expr, "unable to override alignment of packed union fields", .{});
5305 return astgen.failNode(align_node, "unable to override alignment of packed union fields", .{});
53765306 }
5377 const align_inst = try expr(&block_scope, &block_scope.base, coerced_align_ri, align_expr);
5378 wip_members.appendToField(@intFromEnum(align_inst));
5379 any_aligned_fields = true;
5380 }
5381 if (member.ast.value_expr.unwrap()) |value_expr| {
5382 if (arg_inst == .none) {
5383 return astgen.failNodeNotes(
5384 node,
5385 "explicitly valued tagged union missing integer tag type",
5386 .{},
5387 &[_]u32{
5388 try astgen.errNoteNode(
5389 value_expr,
5390 "tag value specified here",
5391 .{},
5392 ),
5393 },
5394 );
5307 const align_ref = try expr(&block_scope, &namespace.base, coerced_align_ri, align_node);
5308 if (!block_scope.endsWithNoReturn()) {
5309 _ = try block_scope.addBreak(.break_inline, decl_inst, align_ref);
53955310 }
5396 if (auto_enum_tok == null) {
5397 return astgen.failNodeNotes(
5398 node,
5399 "explicitly valued tagged union requires inferred enum tag type",
5400 .{},
5401 &[_]u32{
5402 try astgen.errNoteNode(
5403 value_expr,
5404 "tag value specified here",
5405 .{},
5406 ),
5407 },
5408 );
5311 const body_len = try scratch.appendBodyWithFixups(block_scope.instructionsSlice());
5312 field_align_body_lens.?.get(astgen)[field_idx] = body_len;
5313 block_scope.instructions.items.len = block_scope.instructions_top;
5314 } else if (field_align_body_lens) |lens| {
5315 lens.get(astgen)[field_idx] = 0;
5316 }
5317
5318 if (member.ast.value_expr.unwrap()) |value_node| {
5319 if (!explicit_int_or_enum_tag) return astgen.failNodeNotes(
5320 node,
5321 "explicitly valued tagged union missing integer tag type",
5322 .{},
5323 &.{try astgen.errNoteNode(value_node, "tag value specified here", .{})},
5324 );
5325 if (auto_enum_tok == null) return astgen.failNodeNotes(
5326 node,
5327 "explicitly valued tagged union requires inferred enum tag type",
5328 .{},
5329 &.{try astgen.errNoteNode(value_node, "tag value specified here", .{})},
5330 );
5331 const ri: ResultInfo = .{ .rl = .{ .coerced_ty = decl_inst.toRef() } };
5332 const value_ref = try expr(&block_scope, &namespace.base, ri, value_node);
5333 if (!block_scope.endsWithNoReturn()) {
5334 _ = try block_scope.addBreak(.break_inline, decl_inst, value_ref);
54095335 }
5410 const tag_value = try expr(&block_scope, &block_scope.base, .{ .rl = .{ .ty = arg_inst } }, value_expr);
5411 wip_members.appendToField(@intFromEnum(tag_value));
5336 const body_len = try scratch.appendBodyWithFixups(block_scope.instructionsSlice());
5337 field_value_body_lens.?.get(astgen)[field_idx] = body_len;
5338 block_scope.instructions.items.len = block_scope.instructions_top;
5339 } else if (field_value_body_lens) |lens| {
5340 lens.get(astgen)[field_idx] = 0;
54125341 }
54135342 }
5343 assert(next_field_idx == scan_result.fields_len);
5344 wip_decls.finish();
54145345
54155346 var fields_hash: std.zig.SrcHash = undefined;
54165347 astgen.src_hasher.final(&fields_hash);
54175348
5418 if (!block_scope.isEmpty()) {
5419 _ = try block_scope.addBreak(.break_inline, decl_inst, .void_value);
5420 }
5421
5422 const body = block_scope.instructionsSlice();
5423 const body_len = astgen.countBodyLenAfterFixups(body);
5424
54255349 try gz.setUnion(decl_inst, .{
54265350 .src_node = node,
5427 .layout = layout,
5428 .tag_type = arg_inst,
5429 .captures_len = @intCast(namespace.captures.count()),
5430 .body_len = body_len,
5431 .fields_len = field_count,
5432 .decls_len = decl_count,
5433 .auto_enum_tag = auto_enum_tok != null,
5434 .any_aligned_fields = any_aligned_fields,
5435 .fields_hash = fields_hash,
54365351 .name_strat = name_strat,
5352 .kind = switch (layout) {
5353 .auto => if (auto_enum_tok == null) l: {
5354 break :l if (opt_arg_node == .none) .auto else .tagged_explicit;
5355 } else l: {
5356 break :l if (opt_arg_node == .none) .tagged_enum else .tagged_enum_explicit;
5357 },
5358 .@"extern" => .@"extern",
5359 .@"packed" => if (opt_arg_node != .none) .packed_explicit else .@"packed",
5360 },
5361 .arg_type = arg_type_ref,
5362 .decls_len = scan_result.decls_len,
5363 .fields_len = scan_result.fields_len,
5364 .any_field_aligns = scan_result.any_field_aligns,
5365 .any_field_values = scan_result.any_field_values,
5366 .fields_hash = fields_hash,
5367 .captures = namespace.captures.keys(),
5368 .capture_names = namespace.captures.values(),
5369 .remaining = scratch.all().get(astgen),
54375370 });
54385371
5439 wip_members.finishBits(bits_per_field);
5440 const decls_slice = wip_members.declsSlice();
5441 const fields_slice = wip_members.fieldsSlice();
5442 try astgen.extra.ensureUnusedCapacity(gpa, namespace.captures.count() * 2 + decls_slice.len + body_len + fields_slice.len);
5443 astgen.extra.appendSliceAssumeCapacity(@ptrCast(namespace.captures.keys()));
5444 astgen.extra.appendSliceAssumeCapacity(@ptrCast(namespace.captures.values()));
5445 astgen.extra.appendSliceAssumeCapacity(decls_slice);
5446 astgen.appendBodyWithFixups(body);
5447 astgen.extra.appendSliceAssumeCapacity(fields_slice);
5448
54495372 block_scope.unstack();
54505373 return decl_inst.toRef();
54515374}
......@@ -5494,103 +5417,13 @@ fn containerDecl(
54945417 if (container_decl.layout_token) |t| {
54955418 return astgen.failTok(t, "enums do not support 'packed' or 'extern'; instead provide an explicit integer tag type", .{});
54965419 }
5497 // Count total fields as well as how many have explicitly provided tag values.
5498 const counts = blk: {
5499 var values: usize = 0;
5500 var total_fields: usize = 0;
5501 var decls: usize = 0;
5502 var opt_nonexhaustive_node: Ast.Node.OptionalIndex = .none;
5503 var nonfinal_nonexhaustive = false;
5504 for (container_decl.ast.members) |member_node| {
5505 var member = tree.fullContainerField(member_node) orelse {
5506 decls += 1;
5507 continue;
5508 };
5509 member.convertToNonTupleLike(astgen.tree);
5510 if (member.ast.tuple_like) {
5511 return astgen.failTok(member.ast.main_token, "enum field missing name", .{});
5512 }
5513 if (member.comptime_token) |comptime_token| {
5514 return astgen.failTok(comptime_token, "enum fields cannot be marked comptime", .{});
5515 }
5516 if (member.ast.type_expr.unwrap()) |type_expr| {
5517 return astgen.failNodeNotes(
5518 type_expr,
5519 "enum fields do not have types",
5520 .{},
5521 &[_]u32{
5522 try astgen.errNoteNode(
5523 node,
5524 "consider 'union(enum)' here to make it a tagged union",
5525 .{},
5526 ),
5527 },
5528 );
5529 }
5530 if (member.ast.align_expr.unwrap()) |align_expr| {
5531 return astgen.failNode(align_expr, "enum fields cannot be aligned", .{});
5532 }
55335420
5534 const name_token = member.ast.main_token;
5535 if (mem.eql(u8, tree.tokenSlice(name_token), "_")) {
5536 if (opt_nonexhaustive_node.unwrap()) |nonexhaustive_node| {
5537 return astgen.failNodeNotes(
5538 member_node,
5539 "redundant non-exhaustive enum mark",
5540 .{},
5541 &[_]u32{
5542 try astgen.errNoteNode(
5543 nonexhaustive_node,
5544 "other mark here",
5545 .{},
5546 ),
5547 },
5548 );
5549 }
5550 opt_nonexhaustive_node = member_node.toOptional();
5551 if (member.ast.value_expr.unwrap()) |value_expr| {
5552 return astgen.failNode(value_expr, "'_' is used to mark an enum as non-exhaustive and cannot be assigned a value", .{});
5553 }
5554 continue;
5555 } else if (opt_nonexhaustive_node != .none) {
5556 nonfinal_nonexhaustive = true;
5557 }
5558 total_fields += 1;
5559 if (member.ast.value_expr.unwrap()) |value_expr| {
5560 if (container_decl.ast.arg == .none) {
5561 return astgen.failNode(value_expr, "value assigned to enum tag with inferred tag type", .{});
5562 }
5563 values += 1;
5564 }
5565 }
5566 if (nonfinal_nonexhaustive) {
5567 return astgen.failNode(opt_nonexhaustive_node.unwrap().?, "'_' field of non-exhaustive enum must be last", .{});
5568 }
5569 break :blk .{
5570 .total_fields = total_fields,
5571 .values = values,
5572 .decls = decls,
5573 .nonexhaustive_node = opt_nonexhaustive_node,
5574 };
5421 astgen.advanceSourceCursorToNode(node);
5422
5423 const tag_type_ref: Zir.Inst.Ref = ref: {
5424 const arg_node = container_decl.ast.arg.unwrap() orelse break :ref .none;
5425 break :ref try typeExpr(gz, scope, arg_node);
55755426 };
5576 if (counts.nonexhaustive_node != .none and container_decl.ast.arg == .none) {
5577 const nonexhaustive_node = counts.nonexhaustive_node.unwrap().?;
5578 return astgen.failNodeNotes(
5579 node,
5580 "non-exhaustive enum missing integer tag type",
5581 .{},
5582 &[_]u32{
5583 try astgen.errNoteNode(
5584 nonexhaustive_node,
5585 "marked non-exhaustive here",
5586 .{},
5587 ),
5588 },
5589 );
5590 }
5591 // In this case we must generate ZIR code for the tag values, similar to
5592 // how structs are handled above.
5593 const nonexhaustive = counts.nonexhaustive_node != .none;
55945427
55955428 const decl_inst = try gz.reserveInstructionIndex();
55965429
......@@ -5605,7 +5438,6 @@ fn containerDecl(
56055438
56065439 // The enum_decl instruction introduces a scope in which the decls of the enum
56075440 // are in scope, so that tag values can refer to decls within the enum itself.
5608 astgen.advanceSourceCursorToNode(node);
56095441 var block_scope: GenZir = .{
56105442 .parent = &namespace.base,
56115443 .decl_node_index = node,
......@@ -5617,104 +5449,111 @@ fn containerDecl(
56175449 };
56185450 defer block_scope.unstack();
56195451
5620 _ = try astgen.scanContainer(&namespace, container_decl.ast.members, .@"enum");
5621 namespace.base.tag = .namespace;
5452 const scan_result = try astgen.scanContainer(&namespace, container_decl.ast.members, .@"enum");
5453 // The name `_` is not actually a field; it marks a non-exhaustive enum.
5454 const fields_len: u32 = scan_result.fields_len - @intFromBool(scan_result.has_underscore_field);
56225455
5623 const arg_inst: Zir.Inst.Ref = if (container_decl.ast.arg.unwrap()) |arg|
5624 try comptimeExpr(&block_scope, &namespace.base, coerced_type_ri, arg, .type)
5625 else
5626 .none;
5456 var scratch: Scratch = .init(astgen);
5457 defer scratch.reset();
56275458
5628 const bits_per_field = 1;
5629 const max_field_size = 2;
5630 var wip_members = try WipMembers.init(gpa, &astgen.scratch, @intCast(counts.decls), @intCast(counts.total_fields), bits_per_field, max_field_size);
5631 defer wip_members.deinit();
5459 // Replicate the structure of the ZIR trailing data in `scratch`
5460 var wip_decls: WipDecls = try .init(&scratch, scan_result.decls_len);
5461 const field_names = try scratch.addSlice(fields_len);
5462 const field_value_body_lens = try scratch.addOptionalSlice(scan_result.any_field_values, fields_len);
56325463
56335464 const old_hasher = astgen.src_hasher;
56345465 defer astgen.src_hasher = old_hasher;
5635 astgen.src_hasher = std.zig.SrcHasher.init(.{});
5636 if (container_decl.ast.arg.unwrap()) |arg| {
5637 astgen.src_hasher.update(tree.getNodeSource(arg));
5638 }
5639 astgen.src_hasher.update(&.{@intFromBool(nonexhaustive)});
5466 astgen.src_hasher = .init(.{});
56405467
5468 var next_field_idx: u32 = 0;
5469 var opt_nonexhaustive_node: Ast.Node.OptionalIndex = .none;
56415470 for (container_decl.ast.members) |member_node| {
5642 if (member_node.toOptional() == counts.nonexhaustive_node)
5643 continue;
5644 astgen.src_hasher.update(tree.getNodeSource(member_node));
5645 var member = switch (try containerMember(&block_scope, &namespace.base, &wip_members, member_node)) {
5471 var member = switch (try containerMember(&block_scope, &namespace.base, &wip_decls, member_node)) {
56465472 .decl => continue,
56475473 .field => |field| field,
56485474 };
56495475 member.convertToNonTupleLike(astgen.tree);
5650 assert(member.comptime_token == null);
5651 assert(member.ast.type_expr == .none);
5652 assert(member.ast.align_expr == .none);
5476 if (member.ast.tuple_like) return astgen.failTok(member.ast.main_token, "enum field missing name", .{});
5477 if (member.comptime_token) |t| return astgen.failTok(t, "enum fields cannot be marked comptime", .{});
5478 if (member.ast.type_expr.unwrap()) |type_node| {
5479 return astgen.failNodeNotes(type_node, "enum fields do not have types", .{}, &.{
5480 try astgen.errNoteNode(node, "consider 'union(enum)' here to make it a tagged union", .{}),
5481 });
5482 }
5483 if (member.ast.align_expr.unwrap()) |n| return astgen.failNode(n, "enum fields cannot be aligned", .{});
5484 if (mem.eql(u8, tree.tokenSlice(member.ast.main_token), "_")) {
5485 // non-exhaustive mark
5486 assert(scan_result.has_underscore_field);
5487 if (opt_nonexhaustive_node.unwrap()) |prev_node| {
5488 return astgen.failNodeNotes(member_node, "redundant non-exhaustive enum mark", .{}, &.{
5489 try astgen.errNoteNode(prev_node, "other mark here", .{}),
5490 });
5491 }
5492 if (member.ast.value_expr.unwrap()) |value_node| {
5493 return astgen.failNode(value_node, "'_' is used to mark an enum as non-exhaustive and cannot be assigned a value", .{});
5494 }
5495 if (next_field_idx != fields_len) {
5496 return astgen.failNode(member_node, "'_' field of non-exhaustive enum must be last", .{});
5497 }
5498 opt_nonexhaustive_node = member_node.toOptional();
5499 continue;
5500 }
56535501
5654 const field_name = try astgen.identAsString(member.ast.main_token);
5655 wip_members.appendToField(@intFromEnum(field_name));
5502 // This is a real field rather than a non-exhaustive mark.
5503 const field_idx = next_field_idx;
5504 next_field_idx += 1;
56565505
5657 const have_value = member.ast.value_expr != .none;
5658 wip_members.nextField(bits_per_field, .{have_value});
5506 astgen.src_hasher.update(tree.getNodeSource(member_node));
56595507
5660 if (member.ast.value_expr.unwrap()) |value_expr| {
5661 if (arg_inst == .none) {
5662 return astgen.failNodeNotes(
5663 node,
5664 "explicitly valued enum missing integer tag type",
5665 .{},
5666 &[_]u32{
5667 try astgen.errNoteNode(
5668 value_expr,
5669 "tag value specified here",
5670 .{},
5671 ),
5672 },
5673 );
5508 field_names.get(astgen)[field_idx] = @intFromEnum(try astgen.identAsString(member.ast.main_token));
5509
5510 if (member.ast.value_expr.unwrap()) |value_node| {
5511 if (tag_type_ref == .none) {
5512 return astgen.failNodeNotes(node, "explicitly valued enum missing integer tag type", .{}, &.{
5513 try astgen.errNoteNode(value_node, "tag value specified here", .{}),
5514 });
5515 }
5516 const val_ri: ResultInfo = .{ .rl = .{ .coerced_ty = decl_inst.toRef() } };
5517 const value_ref = try expr(&block_scope, &namespace.base, val_ri, value_node);
5518 if (!block_scope.endsWithNoReturn()) {
5519 _ = try block_scope.addBreak(.break_inline, decl_inst, value_ref);
56745520 }
5675 const tag_value_inst = try expr(&block_scope, &namespace.base, .{ .rl = .{ .ty = arg_inst } }, value_expr);
5676 wip_members.appendToField(@intFromEnum(tag_value_inst));
5521 const body_len = try scratch.appendBodyWithFixups(block_scope.instructionsSlice());
5522 field_value_body_lens.?.get(astgen)[field_idx] = body_len;
5523 block_scope.instructions.items.len = block_scope.instructions_top;
5524 } else if (field_value_body_lens) |lens| {
5525 lens.get(astgen)[field_idx] = 0;
56775526 }
56785527 }
5679
5680 if (!block_scope.isEmpty()) {
5681 _ = try block_scope.addBreak(.break_inline, decl_inst, .void_value);
5682 }
5528 assert(scan_result.has_underscore_field == (opt_nonexhaustive_node != .none));
5529 assert(next_field_idx == fields_len);
5530 wip_decls.finish();
56835531
56845532 var fields_hash: std.zig.SrcHash = undefined;
56855533 astgen.src_hasher.final(&fields_hash);
56865534
5687 const body = block_scope.instructionsSlice();
5688 const body_len = astgen.countBodyLenAfterFixups(body);
5689
56905535 try gz.setEnum(decl_inst, .{
56915536 .src_node = node,
5692 .nonexhaustive = nonexhaustive,
5693 .tag_type = arg_inst,
5694 .captures_len = @intCast(namespace.captures.count()),
5695 .body_len = body_len,
5696 .fields_len = @intCast(counts.total_fields),
5697 .decls_len = @intCast(counts.decls),
5698 .fields_hash = fields_hash,
56995537 .name_strat = name_strat,
5538 .tag_type = tag_type_ref,
5539 .nonexhaustive = scan_result.has_underscore_field,
5540 .decls_len = scan_result.decls_len,
5541 .fields_len = fields_len,
5542 .any_field_values = scan_result.any_field_values,
5543 .fields_hash = fields_hash,
5544 .captures = namespace.captures.keys(),
5545 .capture_names = namespace.captures.values(),
5546 .remaining = scratch.all().get(astgen),
57005547 });
57015548
5702 wip_members.finishBits(bits_per_field);
5703 const decls_slice = wip_members.declsSlice();
5704 const fields_slice = wip_members.fieldsSlice();
5705 try astgen.extra.ensureUnusedCapacity(gpa, namespace.captures.count() * 2 + decls_slice.len + body_len + fields_slice.len);
5706 astgen.extra.appendSliceAssumeCapacity(@ptrCast(namespace.captures.keys()));
5707 astgen.extra.appendSliceAssumeCapacity(@ptrCast(namespace.captures.values()));
5708 astgen.extra.appendSliceAssumeCapacity(decls_slice);
5709 astgen.appendBodyWithFixups(body);
5710 astgen.extra.appendSliceAssumeCapacity(fields_slice);
5711
57125549 block_scope.unstack();
57135550 return rvalue(gz, ri, decl_inst.toRef(), node);
57145551 },
57155552 .keyword_opaque => {
57165553 assert(container_decl.ast.arg == .none);
57175554
5555 astgen.advanceSourceCursorToNode(node);
5556
57185557 const decl_inst = try gz.reserveInstructionIndex();
57195558
57205559 var namespace: Scope.Namespace = .{
......@@ -5726,7 +5565,6 @@ fn containerDecl(
57265565 };
57275566 defer namespace.deinit(gpa);
57285567
5729 astgen.advanceSourceCursorToNode(node);
57305568 var block_scope: GenZir = .{
57315569 .parent = &namespace.base,
57325570 .decl_node_index = node,
......@@ -5738,36 +5576,34 @@ fn containerDecl(
57385576 };
57395577 defer block_scope.unstack();
57405578
5741 const decl_count = try astgen.scanContainer(&namespace, container_decl.ast.members, .@"opaque");
5579 const scan_result = try astgen.scanContainer(&namespace, container_decl.ast.members, .@"opaque");
57425580
5743 var wip_members = try WipMembers.init(gpa, &astgen.scratch, decl_count, 0, 0, 0);
5744 defer wip_members.deinit();
5581 var scratch: Scratch = .init(astgen);
5582 defer scratch.reset();
5583 var wip_decls: WipDecls = try .init(&scratch, scan_result.decls_len);
57455584
57465585 if (container_decl.layout_token) |layout_token| {
57475586 return astgen.failTok(layout_token, "opaque types do not support 'packed' or 'extern'", .{});
57485587 }
57495588
57505589 for (container_decl.ast.members) |member_node| {
5751 const res = try containerMember(&block_scope, &namespace.base, &wip_members, member_node);
5752 if (res == .field) {
5753 return astgen.failNode(member_node, "opaque types cannot have fields", .{});
5590 switch (try containerMember(&block_scope, &namespace.base, &wip_decls, member_node)) {
5591 .decl => {},
5592 .field => return astgen.failNode(member_node, "opaque types cannot have fields", .{}),
57545593 }
57555594 }
57565595
5596 wip_decls.finish();
5597
57575598 try gz.setOpaque(decl_inst, .{
57585599 .src_node = node,
5759 .captures_len = @intCast(namespace.captures.count()),
5760 .decls_len = decl_count,
57615600 .name_strat = name_strat,
5601 .decls_len = scan_result.decls_len,
5602 .captures = namespace.captures.keys(),
5603 .capture_names = namespace.captures.values(),
5604 .decls = @ptrCast(scratch.all().get(astgen)),
57625605 });
57635606
5764 wip_members.finishBits(0);
5765 const decls_slice = wip_members.declsSlice();
5766 try astgen.extra.ensureUnusedCapacity(gpa, namespace.captures.count() * 2 + decls_slice.len);
5767 astgen.extra.appendSliceAssumeCapacity(@ptrCast(namespace.captures.keys()));
5768 astgen.extra.appendSliceAssumeCapacity(@ptrCast(namespace.captures.values()));
5769 astgen.extra.appendSliceAssumeCapacity(decls_slice);
5770
57715607 block_scope.unstack();
57725608 return rvalue(gz, ri, decl_inst.toRef(), node);
57735609 },
......@@ -5780,7 +5616,7 @@ const ContainerMemberResult = union(enum) { decl, field: Ast.full.ContainerField
57805616fn containerMember(
57815617 gz: *GenZir,
57825618 scope: *Scope,
5783 wip_members: *WipMembers,
5619 wip_decls: *WipDecls,
57845620 member_node: Ast.Node.Index,
57855621) InnerError!ContainerMemberResult {
57865622 const astgen = gz.astgen;
......@@ -5805,13 +5641,13 @@ fn containerMember(
58055641 else
58065642 .none;
58075643
5808 const prev_decl_index = wip_members.decl_index;
5809 astgen.fnDecl(gz, scope, wip_members, member_node, body, full) catch |err| switch (err) {
5644 const prev_decl_index = wip_decls.index;
5645 astgen.fnDecl(gz, scope, wip_decls, member_node, body, full) catch |err| switch (err) {
58105646 error.OutOfMemory => return error.OutOfMemory,
58115647 error.AnalysisFail => {
5812 wip_members.decl_index = prev_decl_index;
5648 wip_decls.index = prev_decl_index;
58135649 try addFailedDeclaration(
5814 wip_members,
5650 wip_decls,
58155651 gz,
58165652 .@"const",
58175653 try astgen.identAsString(full.name_token.?),
......@@ -5828,13 +5664,13 @@ fn containerMember(
58285664 .aligned_var_decl,
58295665 => {
58305666 const full = tree.fullVarDecl(member_node).?;
5831 const prev_decl_index = wip_members.decl_index;
5832 astgen.globalVarDecl(gz, scope, wip_members, member_node, full) catch |err| switch (err) {
5667 const prev_decl_index = wip_decls.index;
5668 astgen.globalVarDecl(gz, scope, wip_decls, member_node, full) catch |err| switch (err) {
58335669 error.OutOfMemory => return error.OutOfMemory,
58345670 error.AnalysisFail => {
5835 wip_members.decl_index = prev_decl_index;
5671 wip_decls.index = prev_decl_index;
58365672 try addFailedDeclaration(
5837 wip_members,
5673 wip_decls,
58385674 gz,
58395675 .@"const", // doesn't really matter
58405676 try astgen.identAsString(full.ast.mut_token + 1),
......@@ -5846,13 +5682,13 @@ fn containerMember(
58465682 },
58475683
58485684 .@"comptime" => {
5849 const prev_decl_index = wip_members.decl_index;
5850 astgen.comptimeDecl(gz, scope, wip_members, member_node) catch |err| switch (err) {
5685 const prev_decl_index = wip_decls.index;
5686 astgen.comptimeDecl(gz, scope, wip_decls, member_node) catch |err| switch (err) {
58515687 error.OutOfMemory => return error.OutOfMemory,
58525688 error.AnalysisFail => {
5853 wip_members.decl_index = prev_decl_index;
5689 wip_decls.index = prev_decl_index;
58545690 try addFailedDeclaration(
5855 wip_members,
5691 wip_decls,
58565692 gz,
58575693 .@"comptime",
58585694 .empty,
......@@ -5863,16 +5699,16 @@ fn containerMember(
58635699 };
58645700 },
58655701 .test_decl => {
5866 const prev_decl_index = wip_members.decl_index;
5702 const prev_decl_index = wip_decls.index;
58675703 // We need to have *some* decl here so that the decl count matches what's expected.
58685704 // Since it doesn't strictly matter *what* this is, let's save ourselves the trouble
58695705 // of duplicating the test name logic, and just assume this is an unnamed test.
5870 astgen.testDecl(gz, scope, wip_members, member_node) catch |err| switch (err) {
5706 astgen.testDecl(gz, scope, wip_decls, member_node) catch |err| switch (err) {
58715707 error.OutOfMemory => return error.OutOfMemory,
58725708 error.AnalysisFail => {
5873 wip_members.decl_index = prev_decl_index;
5709 wip_decls.index = prev_decl_index;
58745710 try addFailedDeclaration(
5875 wip_members,
5711 wip_decls,
58765712 gz,
58775713 .unnamed_test,
58785714 .empty,
......@@ -10619,495 +10455,19 @@ fn nodeMayEvalToError(tree: *const Ast, start_node: Ast.Node.Index) BuiltinFn.Ev
1061910455 }
1062010456}
1062110457
10622/// Returns `true` if it is known the type expression has more than one possible value;
10623/// `false` otherwise.
10624fn nodeImpliesMoreThanOnePossibleValue(tree: *const Ast, start_node: Ast.Node.Index) bool {
10625 var node = start_node;
10626 while (true) {
10627 switch (tree.nodeTag(node)) {
10628 .root,
10629 .test_decl,
10630 .switch_case,
10631 .switch_case_inline,
10632 .switch_case_one,
10633 .switch_case_inline_one,
10634 .container_field_init,
10635 .container_field_align,
10636 .container_field,
10637 .asm_output,
10638 .asm_input,
10639 .global_var_decl,
10640 .local_var_decl,
10641 .simple_var_decl,
10642 .aligned_var_decl,
10643 => unreachable,
10644
10645 .@"return",
10646 .@"break",
10647 .@"continue",
10648 .bit_not,
10649 .bool_not,
10650 .@"defer",
10651 .@"errdefer",
10652 .address_of,
10653 .negation,
10654 .negation_wrap,
10655 .@"resume",
10656 .array_type,
10657 .@"suspend",
10658 .fn_decl,
10659 .anyframe_literal,
10660 .number_literal,
10661 .enum_literal,
10662 .string_literal,
10663 .multiline_string_literal,
10664 .char_literal,
10665 .unreachable_literal,
10666 .error_set_decl,
10667 .container_decl,
10668 .container_decl_trailing,
10669 .container_decl_two,
10670 .container_decl_two_trailing,
10671 .container_decl_arg,
10672 .container_decl_arg_trailing,
10673 .tagged_union,
10674 .tagged_union_trailing,
10675 .tagged_union_two,
10676 .tagged_union_two_trailing,
10677 .tagged_union_enum_tag,
10678 .tagged_union_enum_tag_trailing,
10679 .@"asm",
10680 .asm_simple,
10681 .add,
10682 .add_wrap,
10683 .add_sat,
10684 .array_cat,
10685 .array_mult,
10686 .assign,
10687 .assign_destructure,
10688 .assign_bit_and,
10689 .assign_bit_or,
10690 .assign_shl,
10691 .assign_shl_sat,
10692 .assign_shr,
10693 .assign_bit_xor,
10694 .assign_div,
10695 .assign_sub,
10696 .assign_sub_wrap,
10697 .assign_sub_sat,
10698 .assign_mod,
10699 .assign_add,
10700 .assign_add_wrap,
10701 .assign_add_sat,
10702 .assign_mul,
10703 .assign_mul_wrap,
10704 .assign_mul_sat,
10705 .bang_equal,
10706 .bit_and,
10707 .bit_or,
10708 .shl,
10709 .shl_sat,
10710 .shr,
10711 .bit_xor,
10712 .bool_and,
10713 .bool_or,
10714 .div,
10715 .equal_equal,
10716 .error_union,
10717 .greater_or_equal,
10718 .greater_than,
10719 .less_or_equal,
10720 .less_than,
10721 .merge_error_sets,
10722 .mod,
10723 .mul,
10724 .mul_wrap,
10725 .mul_sat,
10726 .switch_range,
10727 .for_range,
10728 .field_access,
10729 .sub,
10730 .sub_wrap,
10731 .sub_sat,
10732 .slice,
10733 .slice_open,
10734 .slice_sentinel,
10735 .deref,
10736 .array_access,
10737 .error_value,
10738 .while_simple,
10739 .while_cont,
10740 .for_simple,
10741 .if_simple,
10742 .@"catch",
10743 .@"orelse",
10744 .array_init_one,
10745 .array_init_one_comma,
10746 .array_init_dot_two,
10747 .array_init_dot_two_comma,
10748 .array_init_dot,
10749 .array_init_dot_comma,
10750 .array_init,
10751 .array_init_comma,
10752 .struct_init_one,
10753 .struct_init_one_comma,
10754 .struct_init_dot_two,
10755 .struct_init_dot_two_comma,
10756 .struct_init_dot,
10757 .struct_init_dot_comma,
10758 .struct_init,
10759 .struct_init_comma,
10760 .@"while",
10761 .@"if",
10762 .@"for",
10763 .@"switch",
10764 .switch_comma,
10765 .call_one,
10766 .call_one_comma,
10767 .call,
10768 .call_comma,
10769 .block_two,
10770 .block_two_semicolon,
10771 .block,
10772 .block_semicolon,
10773 .builtin_call,
10774 .builtin_call_comma,
10775 .builtin_call_two,
10776 .builtin_call_two_comma,
10777 // these are function bodies, not pointers
10778 .fn_proto_simple,
10779 .fn_proto_multi,
10780 .fn_proto_one,
10781 .fn_proto,
10782 => return false,
10783
10784 // Forward the question to the LHS sub-expression.
10785 .@"try",
10786 .@"comptime",
10787 .@"nosuspend",
10788 => node = tree.nodeData(node).node,
10789 .grouped_expression,
10790 .unwrap_optional,
10791 => node = tree.nodeData(node).node_and_token[0],
10792
10793 .ptr_type_aligned,
10794 .ptr_type_sentinel,
10795 .ptr_type,
10796 .ptr_type_bit_range,
10797 .optional_type,
10798 .anyframe_type,
10799 .array_type_sentinel,
10800 => return true,
10801
10802 .identifier => {
10803 const ident_bytes = tree.tokenSlice(tree.nodeMainToken(node));
10804 if (primitive_instrs.get(ident_bytes)) |primitive| switch (primitive) {
10805 .anyerror_type,
10806 .anyframe_type,
10807 .anyopaque_type,
10808 .bool_type,
10809 .c_int_type,
10810 .c_long_type,
10811 .c_longdouble_type,
10812 .c_longlong_type,
10813 .c_char_type,
10814 .c_short_type,
10815 .c_uint_type,
10816 .c_ulong_type,
10817 .c_ulonglong_type,
10818 .c_ushort_type,
10819 .comptime_float_type,
10820 .comptime_int_type,
10821 .f16_type,
10822 .f32_type,
10823 .f64_type,
10824 .f80_type,
10825 .f128_type,
10826 .i16_type,
10827 .i32_type,
10828 .i64_type,
10829 .i128_type,
10830 .i8_type,
10831 .isize_type,
10832 .type_type,
10833 .u16_type,
10834 .u29_type,
10835 .u32_type,
10836 .u64_type,
10837 .u128_type,
10838 .u1_type,
10839 .u8_type,
10840 .usize_type,
10841 => return true,
10842
10843 .void_type,
10844 .bool_false,
10845 .bool_true,
10846 .null_value,
10847 .undef,
10848 .noreturn_type,
10849 => return false,
10850
10851 else => unreachable, // that's all the values from `primitives`.
10852 } else {
10853 return false;
10854 }
10855 },
10856 }
10857 }
10858}
10859
10860/// Returns `true` if it is known the expression is a type that cannot be used at runtime;
10861/// `false` otherwise.
10862fn nodeImpliesComptimeOnly(tree: *const Ast, start_node: Ast.Node.Index) bool {
10863 var node = start_node;
10864 while (true) {
10865 switch (tree.nodeTag(node)) {
10866 .root,
10867 .test_decl,
10868 .switch_case,
10869 .switch_case_inline,
10870 .switch_case_one,
10871 .switch_case_inline_one,
10872 .container_field_init,
10873 .container_field_align,
10874 .container_field,
10875 .asm_output,
10876 .asm_input,
10877 .global_var_decl,
10878 .local_var_decl,
10879 .simple_var_decl,
10880 .aligned_var_decl,
10881 => unreachable,
10882
10883 .@"return",
10884 .@"break",
10885 .@"continue",
10886 .bit_not,
10887 .bool_not,
10888 .@"defer",
10889 .@"errdefer",
10890 .address_of,
10891 .negation,
10892 .negation_wrap,
10893 .@"resume",
10894 .array_type,
10895 .@"suspend",
10896 .fn_decl,
10897 .anyframe_literal,
10898 .number_literal,
10899 .enum_literal,
10900 .string_literal,
10901 .multiline_string_literal,
10902 .char_literal,
10903 .unreachable_literal,
10904 .error_set_decl,
10905 .container_decl,
10906 .container_decl_trailing,
10907 .container_decl_two,
10908 .container_decl_two_trailing,
10909 .container_decl_arg,
10910 .container_decl_arg_trailing,
10911 .tagged_union,
10912 .tagged_union_trailing,
10913 .tagged_union_two,
10914 .tagged_union_two_trailing,
10915 .tagged_union_enum_tag,
10916 .tagged_union_enum_tag_trailing,
10917 .@"asm",
10918 .asm_simple,
10919 .add,
10920 .add_wrap,
10921 .add_sat,
10922 .array_cat,
10923 .array_mult,
10924 .assign,
10925 .assign_destructure,
10926 .assign_bit_and,
10927 .assign_bit_or,
10928 .assign_shl,
10929 .assign_shl_sat,
10930 .assign_shr,
10931 .assign_bit_xor,
10932 .assign_div,
10933 .assign_sub,
10934 .assign_sub_wrap,
10935 .assign_sub_sat,
10936 .assign_mod,
10937 .assign_add,
10938 .assign_add_wrap,
10939 .assign_add_sat,
10940 .assign_mul,
10941 .assign_mul_wrap,
10942 .assign_mul_sat,
10943 .bang_equal,
10944 .bit_and,
10945 .bit_or,
10946 .shl,
10947 .shl_sat,
10948 .shr,
10949 .bit_xor,
10950 .bool_and,
10951 .bool_or,
10952 .div,
10953 .equal_equal,
10954 .error_union,
10955 .greater_or_equal,
10956 .greater_than,
10957 .less_or_equal,
10958 .less_than,
10959 .merge_error_sets,
10960 .mod,
10961 .mul,
10962 .mul_wrap,
10963 .mul_sat,
10964 .switch_range,
10965 .for_range,
10966 .field_access,
10967 .sub,
10968 .sub_wrap,
10969 .sub_sat,
10970 .slice,
10971 .slice_open,
10972 .slice_sentinel,
10973 .deref,
10974 .array_access,
10975 .error_value,
10976 .while_simple,
10977 .while_cont,
10978 .for_simple,
10979 .if_simple,
10980 .@"catch",
10981 .@"orelse",
10982 .array_init_one,
10983 .array_init_one_comma,
10984 .array_init_dot_two,
10985 .array_init_dot_two_comma,
10986 .array_init_dot,
10987 .array_init_dot_comma,
10988 .array_init,
10989 .array_init_comma,
10990 .struct_init_one,
10991 .struct_init_one_comma,
10992 .struct_init_dot_two,
10993 .struct_init_dot_two_comma,
10994 .struct_init_dot,
10995 .struct_init_dot_comma,
10996 .struct_init,
10997 .struct_init_comma,
10998 .@"while",
10999 .@"if",
11000 .@"for",
11001 .@"switch",
11002 .switch_comma,
11003 .call_one,
11004 .call_one_comma,
11005 .call,
11006 .call_comma,
11007 .block_two,
11008 .block_two_semicolon,
11009 .block,
11010 .block_semicolon,
11011 .builtin_call,
11012 .builtin_call_comma,
11013 .builtin_call_two,
11014 .builtin_call_two_comma,
11015 .ptr_type_aligned,
11016 .ptr_type_sentinel,
11017 .ptr_type,
11018 .ptr_type_bit_range,
11019 .optional_type,
11020 .anyframe_type,
11021 .array_type_sentinel,
11022 => return false,
11023
11024 // these are function bodies, not pointers
11025 .fn_proto_simple,
11026 .fn_proto_multi,
11027 .fn_proto_one,
11028 .fn_proto,
11029 => return true,
11030
11031 // Forward the question to the LHS sub-expression.
11032 .@"try",
11033 .@"comptime",
11034 .@"nosuspend",
11035 => node = tree.nodeData(node).node,
11036 .grouped_expression,
11037 .unwrap_optional,
11038 => node = tree.nodeData(node).node_and_token[0],
11039
11040 .identifier => {
11041 const ident_bytes = tree.tokenSlice(tree.nodeMainToken(node));
11042 if (primitive_instrs.get(ident_bytes)) |primitive| switch (primitive) {
11043 .anyerror_type,
11044 .anyframe_type,
11045 .anyopaque_type,
11046 .bool_type,
11047 .c_int_type,
11048 .c_long_type,
11049 .c_longdouble_type,
11050 .c_longlong_type,
11051 .c_char_type,
11052 .c_short_type,
11053 .c_uint_type,
11054 .c_ulong_type,
11055 .c_ulonglong_type,
11056 .c_ushort_type,
11057 .f16_type,
11058 .f32_type,
11059 .f64_type,
11060 .f80_type,
11061 .f128_type,
11062 .i16_type,
11063 .i32_type,
11064 .i64_type,
11065 .i128_type,
11066 .i8_type,
11067 .isize_type,
11068 .u16_type,
11069 .u29_type,
11070 .u32_type,
11071 .u64_type,
11072 .u128_type,
11073 .u1_type,
11074 .u8_type,
11075 .usize_type,
11076 .void_type,
11077 .bool_false,
11078 .bool_true,
11079 .null_value,
11080 .undef,
11081 .noreturn_type,
11082 => return false,
11083
11084 .comptime_float_type,
11085 .comptime_int_type,
11086 .type_type,
11087 => return true,
11088
11089 else => unreachable, // that's all the values from `primitives`.
11090 } else {
11091 return false;
11092 }
11093 },
11094 }
11095 }
11096}
11097
11098/// Applies `rl` semantics to `result`. Expressions which do not do their own handling of
11099/// result locations must call this function on their result.
11100/// As an example, if `ri.rl` is `.ptr`, it will write the result to the pointer.
11101/// If `ri.rl` is `.ty`, it will coerce the result to the type.
11102/// Assumes nothing stacked on `gz`.
11103fn rvalue(
11104 gz: *GenZir,
11105 ri: ResultInfo,
11106 raw_result: Zir.Inst.Ref,
11107 src_node: Ast.Node.Index,
11108) InnerError!Zir.Inst.Ref {
11109 return rvalueInner(gz, ri, raw_result, src_node, true);
11110}
10458/// Applies `rl` semantics to `result`. Expressions which do not do their own handling of
10459/// result locations must call this function on their result.
10460/// As an example, if `ri.rl` is `.ptr`, it will write the result to the pointer.
10461/// If `ri.rl` is `.ty`, it will coerce the result to the type.
10462/// Assumes nothing stacked on `gz`.
10463fn rvalue(
10464 gz: *GenZir,
10465 ri: ResultInfo,
10466 raw_result: Zir.Inst.Ref,
10467 src_node: Ast.Node.Index,
10468) InnerError!Zir.Inst.Ref {
10469 return rvalueInner(gz, ri, raw_result, src_node, true);
10470}
1111110471
1111210472/// Like `rvalue`, but refuses to perform coercions before taking references for
1111310473/// the `ref_coerced_ty` result type. This is used for local variables which do
......@@ -13044,18 +12404,19 @@ const GenZir = struct {
1304412404
1304512405 fn setStruct(gz: *GenZir, inst: Zir.Inst.Index, args: struct {
1304612406 src_node: Ast.Node.Index,
13047 captures_len: u32,
13048 fields_len: u32,
13049 decls_len: u32,
13050 has_backing_int: bool,
12407 name_strat: Zir.Inst.NameStrategy,
1305112408 layout: std.builtin.Type.ContainerLayout,
13052 known_non_opv: bool,
13053 known_comptime_only: bool,
12409 backing_int_type: Zir.Inst.Ref,
12410 decls_len: u32,
12411 fields_len: u32,
12412 any_field_aligns: bool,
12413 any_field_defaults: bool,
1305412414 any_comptime_fields: bool,
13055 any_default_inits: bool,
13056 any_aligned_fields: bool,
1305712415 fields_hash: std.zig.SrcHash,
13058 name_strat: Zir.Inst.NameStrategy,
12416 captures: []const Zir.Inst.Capture,
12417 capture_names: []const Zir.NullTerminatedString,
12418 /// The trailing declaration list, field information, and body instructions.
12419 remaining: []const u32,
1305912420 }) !void {
1306012421 const astgen = gz.astgen;
1306112422 const gpa = astgen.gpa;
......@@ -13063,9 +12424,16 @@ const GenZir = struct {
1306312424 // Node .root is valid for the root `struct_decl` of a file!
1306412425 assert(args.src_node != .root or gz.parent.tag == .top);
1306512426
12427 const captures_len: u32 = @intCast(args.captures.len);
12428 assert(args.capture_names.len == captures_len);
12429
1306612430 const fields_hash_arr: [4]u32 = @bitCast(args.fields_hash);
1306712431
13068 try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.StructDecl).@"struct".fields.len + 3);
12432 try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.StructDecl).@"struct".fields.len +
12433 4 + // `captures_len`, `decls_len`, `fields_len`, `backing_int_type`
12434 captures_len * 2 + // `capture`, `capture_name`
12435 args.remaining.len);
12436
1306912437 const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.StructDecl{
1307012438 .fields_hash_0 = fields_hash_arr[0],
1307112439 .fields_hash_1 = fields_hash_arr[1],
......@@ -13075,31 +12443,28 @@ const GenZir = struct {
1307512443 .src_node = args.src_node,
1307612444 });
1307712445
13078 if (args.captures_len != 0) {
13079 astgen.extra.appendAssumeCapacity(args.captures_len);
13080 }
13081 if (args.fields_len != 0) {
13082 astgen.extra.appendAssumeCapacity(args.fields_len);
13083 }
13084 if (args.decls_len != 0) {
13085 astgen.extra.appendAssumeCapacity(args.decls_len);
13086 }
12446 if (captures_len != 0) astgen.extra.appendAssumeCapacity(captures_len);
12447 if (args.decls_len != 0) astgen.extra.appendAssumeCapacity(args.decls_len);
12448 if (args.fields_len != 0) astgen.extra.appendAssumeCapacity(args.fields_len);
12449 if (args.backing_int_type != .none) astgen.extra.appendAssumeCapacity(@intFromEnum(args.backing_int_type));
12450 astgen.extra.appendSliceAssumeCapacity(@ptrCast(args.captures));
12451 astgen.extra.appendSliceAssumeCapacity(@ptrCast(args.capture_names));
12452 astgen.extra.appendSliceAssumeCapacity(args.remaining);
12453
1308712454 astgen.instructions.set(@intFromEnum(inst), .{
1308812455 .tag = .extended,
1308912456 .data = .{ .extended = .{
1309012457 .opcode = .struct_decl,
1309112458 .small = @bitCast(Zir.Inst.StructDecl.Small{
13092 .has_captures_len = args.captures_len != 0,
13093 .has_fields_len = args.fields_len != 0,
12459 .has_captures_len = captures_len != 0,
1309412460 .has_decls_len = args.decls_len != 0,
13095 .has_backing_int = args.has_backing_int,
13096 .known_non_opv = args.known_non_opv,
13097 .known_comptime_only = args.known_comptime_only,
12461 .has_fields_len = args.fields_len != 0,
1309812462 .name_strategy = args.name_strat,
1309912463 .layout = args.layout,
12464 .has_backing_int_type = args.backing_int_type != .none,
12465 .any_field_aligns = args.any_field_aligns,
12466 .any_field_defaults = args.any_field_defaults,
1310012467 .any_comptime_fields = args.any_comptime_fields,
13101 .any_default_inits = args.any_default_inits,
13102 .any_aligned_fields = args.any_aligned_fields,
1310312468 }),
1310412469 .operand = payload_index,
1310512470 } },
......@@ -13108,25 +12473,34 @@ const GenZir = struct {
1310812473
1310912474 fn setUnion(gz: *GenZir, inst: Zir.Inst.Index, args: struct {
1311012475 src_node: Ast.Node.Index,
13111 tag_type: Zir.Inst.Ref,
13112 captures_len: u32,
13113 body_len: u32,
13114 fields_len: u32,
12476 name_strat: Zir.Inst.NameStrategy,
12477 kind: Zir.Inst.UnionDecl.Kind,
12478 arg_type: Zir.Inst.Ref,
1311512479 decls_len: u32,
13116 layout: std.builtin.Type.ContainerLayout,
13117 auto_enum_tag: bool,
13118 any_aligned_fields: bool,
12480 fields_len: u32,
12481 any_field_aligns: bool,
12482 any_field_values: bool,
1311912483 fields_hash: std.zig.SrcHash,
13120 name_strat: Zir.Inst.NameStrategy,
12484 captures: []const Zir.Inst.Capture,
12485 capture_names: []const Zir.NullTerminatedString,
12486 /// The trailing declaration list, field information, and body instructions.
12487 remaining: []const u32,
1312112488 }) !void {
1312212489 const astgen = gz.astgen;
1312312490 const gpa = astgen.gpa;
1312412491
1312512492 assert(args.src_node != .root);
1312612493
12494 const captures_len: u32 = @intCast(args.captures.len);
12495 assert(args.capture_names.len == captures_len);
12496
1312712497 const fields_hash_arr: [4]u32 = @bitCast(args.fields_hash);
1312812498
13129 try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.UnionDecl).@"struct".fields.len + 5);
12499 try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.UnionDecl).@"struct".fields.len +
12500 4 + // `captures_len`, `decls_len`, `fields_len`, `backing_int_type`
12501 captures_len * 2 + // `capture`, `capture_name`
12502 args.remaining.len);
12503
1313012504 const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.UnionDecl{
1313112505 .fields_hash_0 = fields_hash_arr[0],
1313212506 .fields_hash_1 = fields_hash_arr[1],
......@@ -13136,60 +12510,68 @@ const GenZir = struct {
1313612510 .src_node = args.src_node,
1313712511 });
1313812512
13139 if (args.tag_type != .none) {
13140 astgen.extra.appendAssumeCapacity(@intFromEnum(args.tag_type));
13141 }
13142 if (args.captures_len != 0) {
13143 astgen.extra.appendAssumeCapacity(args.captures_len);
13144 }
13145 if (args.body_len != 0) {
13146 astgen.extra.appendAssumeCapacity(args.body_len);
13147 }
13148 if (args.fields_len != 0) {
13149 astgen.extra.appendAssumeCapacity(args.fields_len);
13150 }
13151 if (args.decls_len != 0) {
13152 astgen.extra.appendAssumeCapacity(args.decls_len);
12513 if (captures_len != 0) astgen.extra.appendAssumeCapacity(captures_len);
12514 if (args.decls_len != 0) astgen.extra.appendAssumeCapacity(args.decls_len);
12515 if (args.fields_len != 0) astgen.extra.appendAssumeCapacity(args.fields_len);
12516 if (args.kind.hasArgType()) {
12517 assert(args.arg_type != .none);
12518 astgen.extra.appendAssumeCapacity(@intFromEnum(args.arg_type));
12519 } else {
12520 assert(args.arg_type == .none);
1315312521 }
12522 astgen.extra.appendSliceAssumeCapacity(@ptrCast(args.captures));
12523 astgen.extra.appendSliceAssumeCapacity(@ptrCast(args.capture_names));
12524 astgen.extra.appendSliceAssumeCapacity(args.remaining);
12525
1315412526 astgen.instructions.set(@intFromEnum(inst), .{
1315512527 .tag = .extended,
13156 .data = .{ .extended = .{
13157 .opcode = .union_decl,
13158 .small = @bitCast(Zir.Inst.UnionDecl.Small{
13159 .has_tag_type = args.tag_type != .none,
13160 .has_captures_len = args.captures_len != 0,
13161 .has_body_len = args.body_len != 0,
13162 .has_fields_len = args.fields_len != 0,
13163 .has_decls_len = args.decls_len != 0,
13164 .name_strategy = args.name_strat,
13165 .layout = args.layout,
13166 .auto_enum_tag = args.auto_enum_tag,
13167 .any_aligned_fields = args.any_aligned_fields,
13168 }),
13169 .operand = payload_index,
13170 } },
12528 .data = .{
12529 .extended = .{
12530 .opcode = .union_decl,
12531 .small = @bitCast(Zir.Inst.UnionDecl.Small{
12532 .has_captures_len = captures_len != 0,
12533 .has_decls_len = args.decls_len != 0,
12534 .has_fields_len = args.fields_len != 0,
12535 .name_strategy = args.name_strat,
12536 .kind = args.kind,
12537 .any_field_aligns = args.any_field_aligns,
12538 .any_field_values = args.any_field_values,
12539 }),
12540 .operand = payload_index,
12541 },
12542 },
1317112543 });
1317212544 }
1317312545
1317412546 fn setEnum(gz: *GenZir, inst: Zir.Inst.Index, args: struct {
1317512547 src_node: Ast.Node.Index,
12548 name_strat: Zir.Inst.NameStrategy,
1317612549 tag_type: Zir.Inst.Ref,
13177 captures_len: u32,
13178 body_len: u32,
13179 fields_len: u32,
13180 decls_len: u32,
1318112550 nonexhaustive: bool,
12551 decls_len: u32,
12552 fields_len: u32,
12553 any_field_values: bool,
1318212554 fields_hash: std.zig.SrcHash,
13183 name_strat: Zir.Inst.NameStrategy,
12555 captures: []const Zir.Inst.Capture,
12556 capture_names: []const Zir.NullTerminatedString,
12557 /// The trailing declaration list, field information, and body instructions.
12558 remaining: []const u32,
1318412559 }) !void {
1318512560 const astgen = gz.astgen;
1318612561 const gpa = astgen.gpa;
1318712562
1318812563 assert(args.src_node != .root);
1318912564
12565 const captures_len: u32 = @intCast(args.captures.len);
12566 assert(args.capture_names.len == captures_len);
12567
1319012568 const fields_hash_arr: [4]u32 = @bitCast(args.fields_hash);
1319112569
13192 try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.EnumDecl).@"struct".fields.len + 5);
12570 try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.EnumDecl).@"struct".fields.len +
12571 4 + // `captures_len`, `decls_len`, `fields_len`, `tag_type`
12572 captures_len * 2 + // `capture`, `capture_name`
12573 args.remaining.len);
12574
1319312575 const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.EnumDecl{
1319412576 .fields_hash_0 = fields_hash_arr[0],
1319512577 .fields_hash_1 = fields_hash_arr[1],
......@@ -13199,33 +12581,26 @@ const GenZir = struct {
1319912581 .src_node = args.src_node,
1320012582 });
1320112583
13202 if (args.tag_type != .none) {
13203 astgen.extra.appendAssumeCapacity(@intFromEnum(args.tag_type));
13204 }
13205 if (args.captures_len != 0) {
13206 astgen.extra.appendAssumeCapacity(args.captures_len);
13207 }
13208 if (args.body_len != 0) {
13209 astgen.extra.appendAssumeCapacity(args.body_len);
13210 }
13211 if (args.fields_len != 0) {
13212 astgen.extra.appendAssumeCapacity(args.fields_len);
13213 }
13214 if (args.decls_len != 0) {
13215 astgen.extra.appendAssumeCapacity(args.decls_len);
13216 }
12584 if (captures_len != 0) astgen.extra.appendAssumeCapacity(captures_len);
12585 if (args.decls_len != 0) astgen.extra.appendAssumeCapacity(args.decls_len);
12586 if (args.fields_len != 0) astgen.extra.appendAssumeCapacity(args.fields_len);
12587 if (args.tag_type != .none) astgen.extra.appendAssumeCapacity(@intFromEnum(args.tag_type));
12588 astgen.extra.appendSliceAssumeCapacity(@ptrCast(args.captures));
12589 astgen.extra.appendSliceAssumeCapacity(@ptrCast(args.capture_names));
12590 astgen.extra.appendSliceAssumeCapacity(args.remaining);
12591
1321712592 astgen.instructions.set(@intFromEnum(inst), .{
1321812593 .tag = .extended,
1321912594 .data = .{ .extended = .{
1322012595 .opcode = .enum_decl,
1322112596 .small = @bitCast(Zir.Inst.EnumDecl.Small{
13222 .has_tag_type = args.tag_type != .none,
13223 .has_captures_len = args.captures_len != 0,
13224 .has_body_len = args.body_len != 0,
13225 .has_fields_len = args.fields_len != 0,
12597 .has_captures_len = captures_len != 0,
1322612598 .has_decls_len = args.decls_len != 0,
12599 .has_fields_len = args.fields_len != 0,
1322712600 .name_strategy = args.name_strat,
12601 .has_tag_type = args.tag_type != .none,
1322812602 .nonexhaustive = args.nonexhaustive,
12603 .any_field_values = args.any_field_values,
1322912604 }),
1323012605 .operand = payload_index,
1323112606 } },
......@@ -13234,33 +12609,41 @@ const GenZir = struct {
1323412609
1323512610 fn setOpaque(gz: *GenZir, inst: Zir.Inst.Index, args: struct {
1323612611 src_node: Ast.Node.Index,
13237 captures_len: u32,
13238 decls_len: u32,
1323912612 name_strat: Zir.Inst.NameStrategy,
12613 decls_len: u32,
12614 captures: []const Zir.Inst.Capture,
12615 capture_names: []const Zir.NullTerminatedString,
12616 decls: []const Zir.Inst.Index,
1324012617 }) !void {
1324112618 const astgen = gz.astgen;
1324212619 const gpa = astgen.gpa;
1324312620
1324412621 assert(args.src_node != .root);
1324512622
13246 try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.OpaqueDecl).@"struct".fields.len + 2);
12623 const captures_len: u32 = @intCast(args.captures.len);
12624 assert(args.capture_names.len == captures_len);
12625
12626 try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.OpaqueDecl).@"struct".fields.len +
12627 2 + // `captures_len`, `decls_len`
12628 captures_len * 2 + // `capture`, `capture_name`
12629 args.decls.len);
12630
1324712631 const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.OpaqueDecl{
1324812632 .src_line = astgen.source_line,
1324912633 .src_node = args.src_node,
1325012634 });
12635 if (captures_len != 0) astgen.extra.appendAssumeCapacity(captures_len);
12636 if (args.decls_len != 0) astgen.extra.appendAssumeCapacity(args.decls_len);
12637 astgen.extra.appendSliceAssumeCapacity(@ptrCast(args.captures));
12638 astgen.extra.appendSliceAssumeCapacity(@ptrCast(args.capture_names));
12639 astgen.extra.appendSliceAssumeCapacity(@ptrCast(args.decls));
1325112640
13252 if (args.captures_len != 0) {
13253 astgen.extra.appendAssumeCapacity(args.captures_len);
13254 }
13255 if (args.decls_len != 0) {
13256 astgen.extra.appendAssumeCapacity(args.decls_len);
13257 }
1325812641 astgen.instructions.set(@intFromEnum(inst), .{
1325912642 .tag = .extended,
1326012643 .data = .{ .extended = .{
1326112644 .opcode = .opaque_decl,
1326212645 .small = @bitCast(Zir.Inst.OpaqueDecl.Small{
13263 .has_captures_len = args.captures_len != 0,
12646 .has_captures_len = captures_len != 0,
1326412647 .has_decls_len = args.decls_len != 0,
1326512648 .name_strategy = args.name_strat,
1326612649 }),
......@@ -13484,14 +12867,24 @@ fn restoreSourceCursor(astgen: *AstGen, cursor: SourceCursor) void {
1348412867 astgen.source_column = cursor.column;
1348512868}
1348612869
12870const ScanContainerResult = struct {
12871 /// Includes unnamed declarations (e.g. `comptime` decls)
12872 decls_len: u32,
12873 fields_len: u32,
12874 any_field_aligns: bool,
12875 any_field_values: bool,
12876 any_comptime_fields: bool,
12877 /// Whether there is a field named `_` (indicating a non-exhaustive enum)
12878 has_underscore_field: bool,
12879};
12880
1348712881/// Detects name conflicts for decls and fields, and populates `namespace.decls` with all named declarations.
13488/// Returns the number of declarations in the namespace, including unnamed declarations (e.g. `comptime` decls).
1348912882fn scanContainer(
1349012883 astgen: *AstGen,
1349112884 namespace: *Scope.Namespace,
1349212885 members: []const Ast.Node.Index,
1349312886 container_kind: enum { @"struct", @"union", @"enum", @"opaque" },
13494) !u32 {
12887) !ScanContainerResult {
1349512888 const gpa = astgen.gpa;
1349612889 const tree = astgen.tree;
1349712890
......@@ -13521,6 +12914,10 @@ fn scanContainer(
1352112914
1352212915 var any_duplicates = false;
1352312916 var decl_count: u32 = 0;
12917 var any_field_aligns = false;
12918 var any_field_values = false;
12919 var any_comptime_fields = false;
12920 var has_underscore_field = false;
1352412921 for (members) |member_node| {
1352512922 const Kind = enum { decl, field };
1352612923 const kind: Kind, const name_token = switch (tree.nodeTag(member_node)) {
......@@ -13533,6 +12930,10 @@ fn scanContainer(
1353312930 .@"struct", .@"opaque" => {},
1353412931 .@"union", .@"enum" => full.convertToNonTupleLike(astgen.tree),
1353512932 }
12933 if (full.ast.align_expr != .none) any_field_aligns = true;
12934 if (full.ast.value_expr != .none) any_field_values = true;
12935 if (full.comptime_token != null) any_comptime_fields = true;
12936 if (mem.eql(u8, tree.tokenSlice(full.ast.main_token), "_")) has_underscore_field = true;
1353612937 if (full.ast.tuple_like) continue;
1353712938 break :blk .{ .field, full.ast.main_token };
1353812939 },
......@@ -13698,7 +13099,14 @@ fn scanContainer(
1369813099
1369913100 if (!any_duplicates) {
1370013101 if (any_invalid_declarations) return error.AnalysisFail;
13701 return decl_count;
13102 return .{
13103 .decls_len = decl_count,
13104 .fields_len = @intCast(members.len - decl_count),
13105 .any_field_aligns = any_field_aligns,
13106 .any_field_values = any_field_values,
13107 .any_comptime_fields = any_comptime_fields,
13108 .has_underscore_field = has_underscore_field,
13109 };
1370213110 }
1370313111
1370413112 for (names.keys(), names.values()) |name, first| {
......@@ -13954,7 +13362,7 @@ const DeclarationName = union(enum) {
1395413362};
1395513363
1395613364fn addFailedDeclaration(
13957 wip_members: *WipMembers,
13365 wip_decls: *WipDecls,
1395813366 gz: *GenZir,
1395913367 kind: Zir.Inst.Declaration.Unwrapped.Kind,
1396013368 name: Zir.NullTerminatedString,
......@@ -13962,7 +13370,7 @@ fn addFailedDeclaration(
1396213370 is_pub: bool,
1396313371) !void {
1396413372 const decl_inst = try gz.makeDeclaration(src_node);
13965 wip_members.nextDecl(decl_inst);
13373 wip_decls.nextDecl(decl_inst);
1396613374
1396713375 var dummy_gz = gz.makeSubBlock(&gz.base);
1396813376
lib/std/zig/Zir.zig+564-378
......@@ -2443,7 +2443,7 @@ pub const Inst = struct {
24432443 has_align: bool,
24442444 has_addrspace: bool,
24452445 has_bit_range: bool,
2446 _: u1 = undefined,
2446 _: u1 = 0,
24472447 },
24482448 size: std.builtin.Type.Pointer.Size,
24492449 /// Index into extra. See `PtrType`.
......@@ -2668,7 +2668,7 @@ pub const Inst = struct {
26682668 has_ret_ty_body: bool,
26692669 has_any_noalias: bool,
26702670 ret_ty_is_generic: bool,
2671 _: u23 = undefined,
2671 _: u23 = 0,
26722672 };
26732673 };
26742674
......@@ -3134,7 +3134,7 @@ pub const Inst = struct {
31343134 pub const Flags = packed struct {
31353135 is_nosuspend: bool,
31363136 ensure_result_used: bool,
3137 _: u30 = undefined,
3137 _: u30 = 0,
31383138
31393139 comptime {
31403140 if (@sizeOf(Flags) != 4 or @bitSizeOf(Flags) != 32)
......@@ -3462,33 +3462,20 @@ pub const Inst = struct {
34623462 };
34633463
34643464 /// Trailing:
3465 /// 0. captures_len: u32 // if has_captures_len
3466 /// 1. fields_len: u32, // if has_fields_len
3467 /// 2. decls_len: u32, // if has_decls_len
3468 /// 3. capture: Capture // for every captures_len
3469 /// 4. capture_name: NullTerminatedString // for every captures_len
3470 /// 5. backing_int_body_len: u32, // if has_backing_int
3471 /// 6. backing_int_ref: Ref, // if has_backing_int and backing_int_body_len is 0
3472 /// 7. backing_int_body_inst: Inst, // if has_backing_int and backing_int_body_len is > 0
3473 /// 8. decl: Index, // for every decls_len; points to a `declaration` instruction
3474 /// 9. flags: u32 // for every 8 fields
3475 /// - sets of 4 bits:
3476 /// 0b000X: whether corresponding field has an align expression
3477 /// 0b00X0: whether corresponding field has a default expression
3478 /// 0b0X00: whether corresponding field is comptime
3479 /// 0bX000: whether corresponding field has a type expression
3480 /// 10. fields: { // for every fields_len
3481 /// field_name: u32,
3482 /// field_type: Ref, // if corresponding bit is not set. none means anytype.
3483 /// field_type_body_len: u32, // if corresponding bit is set
3484 /// align_body_len: u32, // if corresponding bit is set
3485 /// init_body_len: u32, // if corresponding bit is set
3486 /// }
3487 /// 11. bodies: { // for every fields_len
3488 /// field_type_body_inst: Inst, // for each field_type_body_len
3489 /// align_body_inst: Inst, // for each align_body_len
3490 /// init_body_inst: Inst, // for each init_body_len
3491 /// }
3465 /// 0. captures_len: u32 // if `has_captures_len`
3466 /// 1. decls_len: u32, // if `has_decls_len`
3467 /// 2. fields_len: u32, // if `has_fields_len`
3468 /// 3. backing_int_type: Ref // if `has_backing_int`
3469 /// 4. capture: Capture // for every `captures_len`
3470 /// 5. capture_name: NullTerminatedString // for every `captures_len`
3471 /// 6. decl: Index, // for every `decls_len`; points to a `declaration` instruction
3472 /// 7. field_name: NullTerminatedString // for every `fields_len`
3473 /// 8. field_type_body_len: u32 // for every `fields_len`
3474 /// 9. field_align_body_len: u32 // for every `fields_len` if `any_field_aligns`
3475 /// 10. field_default_body_len: u32 // for every `fields_len` if `any_field_defaults`
3476 /// 11. field_comptime_bits: u32 // one bit per `fields_len` if `any_comptime_fields`
3477 /// // LSB is first field, minimum number of `u32` needed
3478 /// 12. body_inst: Inst.Index // type body, then align body, then default body, for each field
34923479 pub const StructDecl = struct {
34933480 // These fields should be concatenated and reinterpreted as a `std.zig.SrcHash`.
34943481 // This hash contains the source of all fields, and any specified attributes (`extern`, backing type, etc).
......@@ -3500,19 +3487,18 @@ pub const Inst = struct {
35003487 /// This node provides a new absolute baseline node for all instructions within this struct.
35013488 src_node: Ast.Node.Index,
35023489
3503 pub const Small = packed struct {
3490 pub const Small = packed struct(u16) {
35043491 has_captures_len: bool,
3505 has_fields_len: bool,
35063492 has_decls_len: bool,
3507 has_backing_int: bool,
3508 known_non_opv: bool,
3509 known_comptime_only: bool,
3493 has_fields_len: bool,
35103494 name_strategy: NameStrategy,
35113495 layout: std.builtin.Type.ContainerLayout,
3512 any_default_inits: bool,
3496 /// Always `false` if `layout != .@"packed"`.
3497 has_backing_int_type: bool,
3498 any_field_aligns: bool,
3499 any_field_defaults: bool,
35133500 any_comptime_fields: bool,
3514 any_aligned_fields: bool,
3515 _: u3 = undefined,
3501 _: u5 = 0,
35163502 };
35173503 };
35183504
......@@ -3633,21 +3619,16 @@ pub const Inst = struct {
36333619 };
36343620
36353621 /// Trailing:
3636 /// 0. tag_type: Ref, // if has_tag_type
3637 /// 1. captures_len: u32, // if has_captures_len
3638 /// 2. body_len: u32, // if has_body_len
3639 /// 3. fields_len: u32, // if has_fields_len
3640 /// 4. decls_len: u32, // if has_decls_len
3641 /// 5. capture: Capture // for every captures_len
3642 /// 6. capture_name: NullTerminatedString // for every captures_len
3643 /// 7. decl: Index, // for every decls_len; points to a `declaration` instruction
3644 /// 8. inst: Index // for every body_len
3645 /// 9. has_bits: u32 // for every 32 fields
3646 /// - the bit is whether corresponding field has an value expression
3647 /// 10. fields: { // for every fields_len
3648 /// field_name: u32,
3649 /// value: Ref, // if corresponding bit is set
3650 /// }
3622 /// 0. captures_len: u32, // if has_captures_len
3623 /// 1. decls_len: u32, // if has_decls_len
3624 /// 2. fields_len: u32, // if has_fields_len
3625 /// 3. tag_type: Ref, // if has_tag_type
3626 /// 4. capture: Capture // for every `captures_len`
3627 /// 5. capture_name: NullTerminatedString // for every `captures_len`
3628 /// 6. decl: Index, // for every `decls_len`; points to a `declaration` instruction
3629 /// 7. field_name: NullTerminatedString // for every `fields_len`
3630 /// 8. field_value_body_len: u32 // for every `fields_len` if `any_field_values`
3631 /// 9. body_inst: Inst.Index // value body for each field
36513632 pub const EnumDecl = struct {
36523633 // These fields should be concatenated and reinterpreted as a `std.zig.SrcHash`.
36533634 // This hash contains the source of all fields, and the backing type if specified.
......@@ -3659,40 +3640,31 @@ pub const Inst = struct {
36593640 /// This node provides a new absolute baseline node for all instructions within this struct.
36603641 src_node: Ast.Node.Index,
36613642
3662 pub const Small = packed struct {
3663 has_tag_type: bool,
3643 pub const Small = packed struct(u16) {
36643644 has_captures_len: bool,
3665 has_body_len: bool,
3666 has_fields_len: bool,
36673645 has_decls_len: bool,
3646 has_fields_len: bool,
36683647 name_strategy: NameStrategy,
3648 has_tag_type: bool,
36693649 nonexhaustive: bool,
3670 _: u8 = undefined,
3650 any_field_values: bool,
3651 _: u8 = 0,
36713652 };
36723653 };
36733654
36743655 /// Trailing:
3675 /// 0. tag_type: Ref, // if has_tag_type
3676 /// 1. captures_len: u32 // if has_captures_len
3677 /// 2. body_len: u32, // if has_body_len
3678 /// 3. fields_len: u32, // if has_fields_len
3679 /// 4. decls_len: u32, // if has_decls_len
3680 /// 5. capture: Capture // for every captures_len
3681 /// 6. capture_name: NullTerminatedString // for every captures_len
3682 /// 7. decl: Index, // for every decls_len; points to a `declaration` instruction
3683 /// 8. inst: Index // for every body_len
3684 /// 9. has_bits: u32 // for every 8 fields
3685 /// - sets of 4 bits:
3686 /// 0b000X: whether corresponding field has a type expression
3687 /// 0b00X0: whether corresponding field has a align expression
3688 /// 0b0X00: whether corresponding field has a tag value expression
3689 /// 0bX000: unused
3690 /// 10. fields: { // for every fields_len
3691 /// field_name: NullTerminatedString, // null terminated string index
3692 /// field_type: Ref, // if corresponding bit is set
3693 /// align: Ref, // if corresponding bit is set
3694 /// tag_value: Ref, // if corresponding bit is set
3695 /// }
3656 /// 0. captures_len: u32 // if `has_captures_len`
3657 /// 1. decls_len: u32, // if `has_decls_len`
3658 /// 2. fields_len: u32, // if `has_fields_len`
3659 /// 3. arg_type: Ref, // if `kind.hasArgType()`
3660 /// 4. capture: Capture // for every `captures_len`
3661 /// 5. capture_name: NullTerminatedString // for every `captures_len`
3662 /// 6. decl: Index, // for every `decls_len`; points to a `declaration` instruction
3663 /// 7. field_name: NullTerminatedString // for every `fields_len`
3664 /// 8. field_type_body_len: u32 // for every `fields_len`
3665 /// 9 . field_align_body_len: u32 // for every `fields_len` if `any_field_aligns`
3666 /// 10. field_value_body_len: u32 // for every `fields_len` if `any_field_values`
3667 /// 11. body_inst: Inst.Index // type body, then align body, then value body, for each field
36963668 pub const UnionDecl = struct {
36973669 // These fields should be concatenated and reinterpreted as a `std.zig.SrcHash`.
36983670 // This hash contains the source of all fields, and any specified attributes (`extern` etc).
......@@ -3704,23 +3676,47 @@ pub const Inst = struct {
37043676 /// This node provides a new absolute baseline node for all instructions within this struct.
37053677 src_node: Ast.Node.Index,
37063678
3707 pub const Small = packed struct {
3708 has_tag_type: bool,
3679 pub const Small = packed struct(u16) {
37093680 has_captures_len: bool,
3710 has_body_len: bool,
3711 has_fields_len: bool,
37123681 has_decls_len: bool,
3682 has_fields_len: bool,
37133683 name_strategy: NameStrategy,
3714 layout: std.builtin.Type.ContainerLayout,
3715 /// has_tag_type | auto_enum_tag | result
3716 /// -------------------------------------
3717 /// false | false | union { }
3718 /// false | true | union(enum) { }
3719 /// true | true | union(enum(T)) { }
3720 /// true | false | union(T) { }
3721 auto_enum_tag: bool,
3722 any_aligned_fields: bool,
3723 _: u5 = undefined,
3684 kind: Kind,
3685 any_field_aligns: bool,
3686 any_field_values: bool,
3687 _: u6 = 0,
3688 };
3689
3690 pub const Kind = enum(u3) {
3691 /// `union`
3692 auto,
3693 /// `union(T)`
3694 tagged_explicit,
3695 /// `union(enum)`
3696 tagged_enum,
3697 /// `union(enum(T))`
3698 tagged_enum_explicit,
3699 /// `extern union`
3700 @"extern",
3701 /// `packed union`
3702 @"packed",
3703 /// `packed union(T)`
3704 packed_explicit,
3705
3706 pub fn hasArgType(k: Kind) bool {
3707 return switch (k) {
3708 .auto, .tagged_enum, .@"extern", .@"packed" => false,
3709 .tagged_explicit, .tagged_enum_explicit, .packed_explicit => true,
3710 };
3711 }
3712
3713 pub fn layout(k: Kind) std.builtin.ContainerLayout {
3714 return switch (k) {
3715 .auto, .tagged_explicit, .tagged_enum, .tagged_enum_explicit => .auto,
3716 .@"extern" => .@"extern",
3717 .@"packed", .packed_explicit => .@"packed",
3718 };
3719 }
37243720 };
37253721 };
37263722
......@@ -3735,11 +3731,11 @@ pub const Inst = struct {
37353731 /// This node provides a new absolute baseline node for all instructions within this struct.
37363732 src_node: Ast.Node.Index,
37373733
3738 pub const Small = packed struct {
3734 pub const Small = packed struct(u16) {
37393735 has_captures_len: bool,
37403736 has_decls_len: bool,
37413737 name_strategy: NameStrategy,
3742 _: u12 = undefined,
3738 _: u12 = 0,
37433739 };
37443740 };
37453741
......@@ -3904,12 +3900,12 @@ pub const Inst = struct {
39043900 pub const AllocExtended = struct {
39053901 src_node: Ast.Node.Offset,
39063902
3907 pub const Small = packed struct {
3903 pub const Small = packed struct(u16) {
39083904 has_type: bool,
39093905 has_align: bool,
39103906 is_const: bool,
39113907 is_comptime: bool,
3912 _: u12 = undefined,
3908 _: u12 = 0,
39133909 };
39143910 };
39153911
......@@ -4012,133 +4008,18 @@ pub const Inst = struct {
40124008 };
40134009};
40144010
4011/// MLUGG TODO: delete this!
40154012pub const DeclIterator = struct {
4016 extra_index: u32,
4017 decls_remaining: u32,
4018 zir: Zir,
4019
4013 decls: []const Inst.Index,
4014 index: usize,
40204015 pub fn next(it: *DeclIterator) ?Inst.Index {
4021 if (it.decls_remaining == 0) return null;
4022 const decl_inst: Zir.Inst.Index = @enumFromInt(it.zir.extra[it.extra_index]);
4023 it.extra_index += 1;
4024 it.decls_remaining -= 1;
4025 assert(it.zir.instructions.items(.tag)[@intFromEnum(decl_inst)] == .declaration);
4026 return decl_inst;
4016 if (it.index == it.decls.len) return null;
4017 defer it.index += 1;
4018 return it.decls[it.index];
40274019 }
40284020};
4029
40304021pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator {
4031 const inst = zir.instructions.get(@intFromEnum(decl_inst));
4032 assert(inst.tag == .extended);
4033 const extended = inst.data.extended;
4034 switch (extended.opcode) {
4035 .struct_decl => {
4036 const small: Inst.StructDecl.Small = @bitCast(extended.small);
4037 var extra_index: u32 = @intCast(extended.operand + @typeInfo(Inst.StructDecl).@"struct".fields.len);
4038 const captures_len = if (small.has_captures_len) captures_len: {
4039 const captures_len = zir.extra[extra_index];
4040 extra_index += 1;
4041 break :captures_len captures_len;
4042 } else 0;
4043 extra_index += @intFromBool(small.has_fields_len);
4044 const decls_len = if (small.has_decls_len) decls_len: {
4045 const decls_len = zir.extra[extra_index];
4046 extra_index += 1;
4047 break :decls_len decls_len;
4048 } else 0;
4049
4050 extra_index += captures_len * 2;
4051
4052 if (small.has_backing_int) {
4053 const backing_int_body_len = zir.extra[extra_index];
4054 extra_index += 1; // backing_int_body_len
4055 if (backing_int_body_len == 0) {
4056 extra_index += 1; // backing_int_ref
4057 } else {
4058 extra_index += backing_int_body_len; // backing_int_body_inst
4059 }
4060 }
4061
4062 return .{
4063 .extra_index = extra_index,
4064 .decls_remaining = decls_len,
4065 .zir = zir,
4066 };
4067 },
4068 .enum_decl => {
4069 const small: Inst.EnumDecl.Small = @bitCast(extended.small);
4070 var extra_index: u32 = @intCast(extended.operand + @typeInfo(Inst.EnumDecl).@"struct".fields.len);
4071 extra_index += @intFromBool(small.has_tag_type);
4072 const captures_len = if (small.has_captures_len) captures_len: {
4073 const captures_len = zir.extra[extra_index];
4074 extra_index += 1;
4075 break :captures_len captures_len;
4076 } else 0;
4077 extra_index += @intFromBool(small.has_body_len);
4078 extra_index += @intFromBool(small.has_fields_len);
4079 const decls_len = if (small.has_decls_len) decls_len: {
4080 const decls_len = zir.extra[extra_index];
4081 extra_index += 1;
4082 break :decls_len decls_len;
4083 } else 0;
4084
4085 extra_index += captures_len * 2;
4086
4087 return .{
4088 .extra_index = extra_index,
4089 .decls_remaining = decls_len,
4090 .zir = zir,
4091 };
4092 },
4093 .union_decl => {
4094 const small: Inst.UnionDecl.Small = @bitCast(extended.small);
4095 var extra_index: u32 = @intCast(extended.operand + @typeInfo(Inst.UnionDecl).@"struct".fields.len);
4096 extra_index += @intFromBool(small.has_tag_type);
4097 const captures_len = if (small.has_captures_len) captures_len: {
4098 const captures_len = zir.extra[extra_index];
4099 extra_index += 1;
4100 break :captures_len captures_len;
4101 } else 0;
4102 extra_index += @intFromBool(small.has_body_len);
4103 extra_index += @intFromBool(small.has_fields_len);
4104 const decls_len = if (small.has_decls_len) decls_len: {
4105 const decls_len = zir.extra[extra_index];
4106 extra_index += 1;
4107 break :decls_len decls_len;
4108 } else 0;
4109
4110 extra_index += captures_len * 2;
4111
4112 return .{
4113 .extra_index = extra_index,
4114 .decls_remaining = decls_len,
4115 .zir = zir,
4116 };
4117 },
4118 .opaque_decl => {
4119 const small: Inst.OpaqueDecl.Small = @bitCast(extended.small);
4120 var extra_index: u32 = @intCast(extended.operand + @typeInfo(Inst.OpaqueDecl).@"struct".fields.len);
4121 const decls_len = if (small.has_decls_len) decls_len: {
4122 const decls_len = zir.extra[extra_index];
4123 extra_index += 1;
4124 break :decls_len decls_len;
4125 } else 0;
4126 const captures_len = if (small.has_captures_len) captures_len: {
4127 const captures_len = zir.extra[extra_index];
4128 extra_index += 1;
4129 break :captures_len captures_len;
4130 } else 0;
4131
4132 extra_index += captures_len * 2;
4133
4134 return .{
4135 .extra_index = extra_index,
4136 .decls_remaining = decls_len,
4137 .zir = zir,
4138 };
4139 },
4140 else => unreachable,
4141 }
4022 return .{ .decls = zir.typeDecls(decl_inst), .index = 0 };
41424023}
41434024
41444025/// `DeclContents` contains all "interesting" instructions found within a declaration by `findTrackable`.
......@@ -4524,7 +4405,7 @@ fn findTrackableInner(
45244405 try zir.findTrackableBody(gpa, contents, defers, body);
45254406 },
45264407
4527 // Reifications and opaque declarations need tracking, but have no body.
4408 // Reifications and opaque declarations need tracking, but have no bodies.
45284409 .reify_enum,
45294410 .reify_struct,
45304411 .reify_union,
......@@ -4535,150 +4416,37 @@ fn findTrackableInner(
45354416 .struct_decl => {
45364417 try contents.explicit_types.append(gpa, inst);
45374418
4538 const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small);
4539 const extra = zir.extraData(Zir.Inst.StructDecl, extended.operand);
4540 var extra_index = extra.end;
4541 const captures_len = if (small.has_captures_len) blk: {
4542 const captures_len = zir.extra[extra_index];
4543 extra_index += 1;
4544 break :blk captures_len;
4545 } else 0;
4546 const fields_len = if (small.has_fields_len) blk: {
4547 const fields_len = zir.extra[extra_index];
4548 extra_index += 1;
4549 break :blk fields_len;
4550 } else 0;
4551 const decls_len = if (small.has_decls_len) blk: {
4552 const decls_len = zir.extra[extra_index];
4553 extra_index += 1;
4554 break :blk decls_len;
4555 } else 0;
4556 extra_index += captures_len * 2;
4557 if (small.has_backing_int) {
4558 const backing_int_body_len = zir.extra[extra_index];
4559 extra_index += 1;
4560 if (backing_int_body_len == 0) {
4561 extra_index += 1; // backing_int_ref
4562 } else {
4563 const body = zir.bodySlice(extra_index, backing_int_body_len);
4564 extra_index += backing_int_body_len;
4565 try zir.findTrackableBody(gpa, contents, defers, body);
4566 }
4567 }
4568 extra_index += decls_len;
4569
4570 // This ZIR is structured in a slightly awkward way, so we have to split up the iteration.
4571 // `extra_index` iterates `flags` (bags of bits).
4572 // `fields_extra_index` iterates `fields`.
4573 // We accumulate the total length of bodies into `total_bodies_len`. This is sufficient because
4574 // the bodies are packed together in `extra` and we only need to traverse their instructions (we
4575 // don't really care about the structure).
4576
4577 const bits_per_field = 4;
4578 const fields_per_u32 = 32 / bits_per_field;
4579 const bit_bags_count = std.math.divCeil(usize, fields_len, fields_per_u32) catch unreachable;
4580 var cur_bit_bag: u32 = undefined;
4581
4582 var fields_extra_index = extra_index + bit_bags_count;
4583 var total_bodies_len: u32 = 0;
4584
4585 for (0..fields_len) |field_i| {
4586 if (field_i % fields_per_u32 == 0) {
4587 cur_bit_bag = zir.extra[extra_index];
4588 extra_index += 1;
4589 }
4590
4591 const has_align = @as(u1, @truncate(cur_bit_bag)) != 0;
4592 cur_bit_bag >>= 1;
4593 const has_init = @as(u1, @truncate(cur_bit_bag)) != 0;
4594 cur_bit_bag >>= 2; // also skip `is_comptime`; we don't care
4595 const has_type_body = @as(u1, @truncate(cur_bit_bag)) != 0;
4596 cur_bit_bag >>= 1;
4597
4598 fields_extra_index += 1; // field_name
4599
4600 if (has_type_body) {
4601 const field_type_body_len = zir.extra[fields_extra_index];
4602 total_bodies_len += field_type_body_len;
4603 }
4604 fields_extra_index += 1; // field_type or field_type_body_len
4605
4606 if (has_align) {
4607 const align_body_len = zir.extra[fields_extra_index];
4608 fields_extra_index += 1;
4609 total_bodies_len += align_body_len;
4610 }
4611
4612 if (has_init) {
4613 const init_body_len = zir.extra[fields_extra_index];
4614 fields_extra_index += 1;
4615 total_bodies_len += init_body_len;
4616 }
4419 const struct_decl = zir.getStructDecl(inst);
4420 var it = struct_decl.iterateFields();
4421 while (it.next()) |field| {
4422 try zir.findTrackableBody(gpa, contents, defers, field.type_body);
4423 if (field.align_body) |b| try zir.findTrackableBody(gpa, contents, defers, b);
4424 if (field.default_body) |b| try zir.findTrackableBody(gpa, contents, defers, b);
46174425 }
4618
4619 // Now, `fields_extra_index` points to `bodies`. Let's treat this as one big body.
4620 const merged_bodies = zir.bodySlice(fields_extra_index, total_bodies_len);
4621 try zir.findTrackableBody(gpa, contents, defers, merged_bodies);
46224426 },
46234427
4624 // Union declarations need tracking and have a body.
4428 // Union declarations need tracking and have bodies.
46254429 .union_decl => {
46264430 try contents.explicit_types.append(gpa, inst);
46274431
4628 const small: Zir.Inst.UnionDecl.Small = @bitCast(extended.small);
4629 const extra = zir.extraData(Zir.Inst.UnionDecl, extended.operand);
4630 var extra_index = extra.end;
4631 extra_index += @intFromBool(small.has_tag_type);
4632 const captures_len = if (small.has_captures_len) blk: {
4633 const captures_len = zir.extra[extra_index];
4634 extra_index += 1;
4635 break :blk captures_len;
4636 } else 0;
4637 const body_len = if (small.has_body_len) blk: {
4638 const body_len = zir.extra[extra_index];
4639 extra_index += 1;
4640 break :blk body_len;
4641 } else 0;
4642 extra_index += @intFromBool(small.has_fields_len);
4643 const decls_len = if (small.has_decls_len) blk: {
4644 const decls_len = zir.extra[extra_index];
4645 extra_index += 1;
4646 break :blk decls_len;
4647 } else 0;
4648 extra_index += captures_len * 2;
4649 extra_index += decls_len;
4650 const body = zir.bodySlice(extra_index, body_len);
4651 try zir.findTrackableBody(gpa, contents, defers, body);
4432 const union_decl = zir.getUnionDecl(inst);
4433 var it = union_decl.iterateFields();
4434 while (it.next()) |field| {
4435 if (field.type_body) |b| try zir.findTrackableBody(gpa, contents, defers, b);
4436 if (field.align_body) |b| try zir.findTrackableBody(gpa, contents, defers, b);
4437 if (field.value_body) |b| try zir.findTrackableBody(gpa, contents, defers, b);
4438 }
46524439 },
46534440
4654 // Enum declarations need tracking and have a body.
4441 // Enum declarations need tracking and have bodies.
46554442 .enum_decl => {
46564443 try contents.explicit_types.append(gpa, inst);
46574444
4658 const small: Zir.Inst.EnumDecl.Small = @bitCast(extended.small);
4659 const extra = zir.extraData(Zir.Inst.EnumDecl, extended.operand);
4660 var extra_index = extra.end;
4661 extra_index += @intFromBool(small.has_tag_type);
4662 const captures_len = if (small.has_captures_len) blk: {
4663 const captures_len = zir.extra[extra_index];
4664 extra_index += 1;
4665 break :blk captures_len;
4666 } else 0;
4667 const body_len = if (small.has_body_len) blk: {
4668 const body_len = zir.extra[extra_index];
4669 extra_index += 1;
4670 break :blk body_len;
4671 } else 0;
4672 extra_index += @intFromBool(small.has_fields_len);
4673 const decls_len = if (small.has_decls_len) blk: {
4674 const decls_len = zir.extra[extra_index];
4675 extra_index += 1;
4676 break :blk decls_len;
4677 } else 0;
4678 extra_index += captures_len * 2;
4679 extra_index += decls_len;
4680 const body = zir.bodySlice(extra_index, body_len);
4681 try zir.findTrackableBody(gpa, contents, defers, body);
4445 const enum_decl = zir.getEnumDecl(inst);
4446 var it = enum_decl.iterateFields();
4447 while (it.next()) |field| {
4448 if (field.value_body) |b| try zir.findTrackableBody(gpa, contents, defers, b);
4449 }
46824450 },
46834451 }
46844452 },
......@@ -5481,34 +5249,452 @@ pub fn assertTrackable(zir: Zir, inst_idx: Zir.Inst.Index) void {
54815249 }
54825250}
54835251
5252/// MLUGG TODO: maybe delete these two?
54845253pub fn typeCapturesLen(zir: Zir, type_decl: Inst.Index) u32 {
54855254 const inst = zir.instructions.get(@intFromEnum(type_decl));
54865255 assert(inst.tag == .extended);
5487 switch (inst.data.extended.opcode) {
5488 .struct_decl => {
5489 const small: Inst.StructDecl.Small = @bitCast(inst.data.extended.small);
5490 if (!small.has_captures_len) return 0;
5491 const extra = zir.extraData(Inst.StructDecl, inst.data.extended.operand);
5492 return zir.extra[extra.end];
5493 },
5494 .union_decl => {
5495 const small: Inst.UnionDecl.Small = @bitCast(inst.data.extended.small);
5496 if (!small.has_captures_len) return 0;
5497 const extra = zir.extraData(Inst.UnionDecl, inst.data.extended.operand);
5498 return zir.extra[extra.end + @intFromBool(small.has_tag_type)];
5499 },
5500 .enum_decl => {
5501 const small: Inst.EnumDecl.Small = @bitCast(inst.data.extended.small);
5502 if (!small.has_captures_len) return 0;
5503 const extra = zir.extraData(Inst.EnumDecl, inst.data.extended.operand);
5504 return zir.extra[extra.end + @intFromBool(small.has_tag_type)];
5505 },
5506 .opaque_decl => {
5507 const small: Inst.OpaqueDecl.Small = @bitCast(inst.data.extended.small);
5508 if (!small.has_captures_len) return 0;
5509 const extra = zir.extraData(Inst.OpaqueDecl, inst.data.extended.operand);
5510 return zir.extra[extra.end];
5511 },
5256 return switch (inst.data.extended.opcode) {
5257 .struct_decl => @intCast(zir.getStructDecl(type_decl).captures.len),
5258 .union_decl => @intCast(zir.getUnionDecl(type_decl).captures.len),
5259 .enum_decl => @intCast(zir.getEnumDecl(type_decl).captures.len),
5260 .opaque_decl => @intCast(zir.getOpaqueDecl(type_decl).captures.len),
55125261 else => unreachable,
5262 };
5263}
5264pub fn typeDecls(zir: Zir, type_decl: Inst.Index) []const Zir.Inst.Index {
5265 const inst = zir.instructions.get(@intFromEnum(type_decl));
5266 assert(inst.tag == .extended);
5267 return switch (inst.data.extended.opcode) {
5268 .struct_decl => zir.getStructDecl(type_decl).decls,
5269 .union_decl => zir.getUnionDecl(type_decl).decls,
5270 .enum_decl => zir.getEnumDecl(type_decl).decls,
5271 .opaque_decl => zir.getOpaqueDecl(type_decl).decls,
5272 else => unreachable,
5273 };
5274}
5275
5276pub fn getStructDecl(zir: *const Zir, struct_decl: Inst.Index) UnwrappedStructDecl {
5277 const inst_data = zir.instructions.get(@intFromEnum(struct_decl));
5278 assert(inst_data.tag == .extended);
5279 assert(inst_data.data.extended.opcode == .struct_decl);
5280 const small: Inst.StructDecl.Small = @bitCast(inst_data.data.extended.small);
5281 const extra = zir.extraData(Inst.StructDecl, inst_data.data.extended.operand);
5282 var extra_index = extra.end;
5283 const captures_len: u32 = if (small.has_captures_len) blk: {
5284 const captures_len = zir.extra[extra_index];
5285 extra_index += 1;
5286 break :blk captures_len;
5287 } else 0;
5288 const decls_len: u32 = if (small.has_decls_len) blk: {
5289 const decls_len = zir.extra[extra_index];
5290 extra_index += 1;
5291 break :blk decls_len;
5292 } else 0;
5293 const fields_len: u32 = if (small.has_fields_len) blk: {
5294 const fields_len = zir.extra[extra_index];
5295 extra_index += 1;
5296 break :blk fields_len;
5297 } else 0;
5298 const backing_int_type: Inst.Ref = if (small.has_backing_int_type) ty: {
5299 const ty = zir.extra[extra_index];
5300 extra_index += 1;
5301 break :ty @enumFromInt(ty);
5302 } else .none;
5303 const captures: []const Inst.Capture = @ptrCast(zir.extra[extra_index..][0..captures_len]);
5304 extra_index += captures_len;
5305 const capture_names: []const NullTerminatedString = @ptrCast(zir.extra[extra_index..][0..captures_len]);
5306 extra_index += captures_len;
5307 const decls: []const Inst.Index = @ptrCast(zir.extra[extra_index..][0..decls_len]);
5308 extra_index += decls_len;
5309 const field_names: []const NullTerminatedString = @ptrCast(zir.extra[extra_index..][0..fields_len]);
5310 extra_index += fields_len;
5311 const field_type_body_lens: []const u32 = @ptrCast(zir.extra[extra_index..][0..fields_len]);
5312 extra_index += fields_len;
5313 const field_align_body_lens: ?[]const u32 = if (small.any_field_aligns) lens: {
5314 const lens = zir.extra[extra_index..][0..fields_len];
5315 extra_index += fields_len;
5316 break :lens @ptrCast(lens);
5317 } else null;
5318 const field_default_body_lens: ?[]const u32 = if (small.any_field_defaults) lens: {
5319 const lens = zir.extra[extra_index..][0..fields_len];
5320 extra_index += fields_len;
5321 break :lens @ptrCast(lens);
5322 } else null;
5323 const field_comptime_bits: ?[]const u32 = if (small.any_comptime_fields) bits: {
5324 const bits_len = std.math.divCeil(u32, fields_len, 32) catch unreachable;
5325 const bits = zir.extra[extra_index..][0..bits_len];
5326 extra_index += bits_len;
5327 break :bits bits;
5328 } else null;
5329 const field_bodies_overlong: []const Inst.Index = @ptrCast(zir.extra[extra_index..]);
5330 return .{
5331 .src_line = extra.data.src_line,
5332 .src_node = extra.data.src_node,
5333 .name_strategy = small.name_strategy,
5334 .captures = captures,
5335 .capture_names = capture_names,
5336 .decls = decls,
5337 .layout = small.layout,
5338 .backing_int_type = backing_int_type,
5339 .field_names = field_names,
5340 .field_type_body_lens = field_type_body_lens,
5341 .field_align_body_lens = field_align_body_lens,
5342 .field_default_body_lens = field_default_body_lens,
5343 .field_comptime_bits = field_comptime_bits,
5344 .field_bodies_overlong = field_bodies_overlong,
5345 };
5346}
5347pub const UnwrappedStructDecl = struct {
5348 src_line: u32,
5349 src_node: Ast.Node.Index,
5350 name_strategy: Inst.NameStrategy,
5351
5352 captures: []const Inst.Capture,
5353 capture_names: []const NullTerminatedString,
5354
5355 decls: []const Inst.Index,
5356
5357 layout: std.builtin.Type.ContainerLayout,
5358 backing_int_type: Inst.Ref,
5359
5360 field_names: []const NullTerminatedString,
5361 field_type_body_lens: []const u32,
5362 field_align_body_lens: ?[]const u32,
5363 field_default_body_lens: ?[]const u32,
5364 field_comptime_bits: ?[]const u32,
5365 field_bodies_overlong: []const Inst.Index,
5366
5367 pub fn iterateFields(struct_decl: UnwrappedStructDecl) FieldIterator {
5368 return .{
5369 .next_idx = 0,
5370 .names = struct_decl.field_names,
5371 .type_body_lens = struct_decl.field_type_body_lens,
5372 .align_body_lens = struct_decl.field_align_body_lens,
5373 .default_body_lens = struct_decl.field_default_body_lens,
5374 .comptime_bits = struct_decl.field_comptime_bits,
5375 .bodies_overlong = struct_decl.field_bodies_overlong,
5376 };
5377 }
5378
5379 pub const FieldIterator = struct {
5380 next_idx: u32,
5381 names: []const NullTerminatedString,
5382 type_body_lens: []const u32,
5383 align_body_lens: ?[]const u32,
5384 default_body_lens: ?[]const u32,
5385 comptime_bits: ?[]const u32,
5386 bodies_overlong: []const Inst.Index,
5387 pub const Field = struct {
5388 idx: u32,
5389 name: NullTerminatedString,
5390 type_body: []const Inst.Index,
5391 align_body: ?[]const Inst.Index,
5392 default_body: ?[]const Inst.Index,
5393 is_comptime: bool,
5394 };
5395 pub fn next(it: *FieldIterator) ?Field {
5396 const idx = it.next_idx;
5397 if (idx == it.names.len) return null;
5398 it.next_idx += 1;
5399 return .{
5400 .idx = idx,
5401 .name = it.names[idx],
5402 .type_body = it.body(it.type_body_lens[idx]).?,
5403 .align_body = it.body(if (it.align_body_lens) |l| l[idx] else 0),
5404 .default_body = it.body(if (it.default_body_lens) |l| l[idx] else 0),
5405 .is_comptime = ct: {
5406 const bits = it.comptime_bits orelse break :ct false;
5407 const big = bits[idx / 32];
5408 const shifted = big >> @intCast(idx % 32);
5409 break :ct @as(u1, @truncate(shifted)) == 1;
5410 },
5411 };
5412 }
5413 fn body(it: *FieldIterator, len: u32) ?[]const Inst.Index {
5414 if (len == 0) return null;
5415 const b = it.bodies_overlong[0..len];
5416 it.bodies_overlong = it.bodies_overlong[len..];
5417 return b;
5418 }
5419 };
5420};
5421
5422pub fn getUnionDecl(zir: *const Zir, union_decl: Inst.Index) UnwrappedUnionDecl {
5423 const inst_data = zir.instructions.get(@intFromEnum(union_decl));
5424 assert(inst_data.tag == .extended);
5425 assert(inst_data.data.extended.opcode == .union_decl);
5426 const small: Inst.UnionDecl.Small = @bitCast(inst_data.data.extended.small);
5427 const extra = zir.extraData(Inst.UnionDecl, inst_data.data.extended.operand);
5428 var extra_index = extra.end;
5429 const captures_len: u32 = if (small.has_captures_len) blk: {
5430 const captures_len = zir.extra[extra_index];
5431 extra_index += 1;
5432 break :blk captures_len;
5433 } else 0;
5434 const decls_len: u32 = if (small.has_decls_len) blk: {
5435 const decls_len = zir.extra[extra_index];
5436 extra_index += 1;
5437 break :blk decls_len;
5438 } else 0;
5439 const fields_len: u32 = if (small.has_fields_len) blk: {
5440 const fields_len = zir.extra[extra_index];
5441 extra_index += 1;
5442 break :blk fields_len;
5443 } else 0;
5444 const arg_type: Inst.Ref = if (small.kind.hasArgType()) ty: {
5445 const ty = zir.extra[extra_index];
5446 extra_index += 1;
5447 break :ty @enumFromInt(ty);
5448 } else .none;
5449 const captures: []const Inst.Capture = @ptrCast(zir.extra[extra_index..][0..captures_len]);
5450 extra_index += captures_len;
5451 const capture_names: []const NullTerminatedString = @ptrCast(zir.extra[extra_index..][0..captures_len]);
5452 extra_index += captures_len;
5453 const decls: []const Inst.Index = @ptrCast(zir.extra[extra_index..][0..decls_len]);
5454 extra_index += decls_len;
5455 const field_names: []const NullTerminatedString = @ptrCast(zir.extra[extra_index..][0..fields_len]);
5456 extra_index += fields_len;
5457 const field_type_body_lens: []const u32 = @ptrCast(zir.extra[extra_index..][0..fields_len]);
5458 extra_index += fields_len;
5459 const field_align_body_lens: ?[]const u32 = if (small.any_field_aligns) lens: {
5460 const lens = zir.extra[extra_index..][0..fields_len];
5461 extra_index += fields_len;
5462 break :lens @ptrCast(lens);
5463 } else null;
5464 const field_value_body_lens: ?[]const u32 = if (small.any_field_values) lens: {
5465 const lens = zir.extra[extra_index..][0..fields_len];
5466 extra_index += fields_len;
5467 break :lens @ptrCast(lens);
5468 } else null;
5469 const field_bodies_overlong: []const Inst.Index = @ptrCast(zir.extra[extra_index..]);
5470 return .{
5471 .src_line = extra.data.src_line,
5472 .src_node = extra.data.src_node,
5473 .name_strategy = small.name_strategy,
5474 .captures = captures,
5475 .capture_names = capture_names,
5476 .decls = decls,
5477 .kind = small.kind,
5478 .arg_type = arg_type,
5479 .field_names = field_names,
5480 .field_type_body_lens = field_type_body_lens,
5481 .field_align_body_lens = field_align_body_lens,
5482 .field_value_body_lens = field_value_body_lens,
5483 .field_bodies_overlong = field_bodies_overlong,
5484 };
5485}
5486pub const UnwrappedUnionDecl = struct {
5487 src_line: u32,
5488 src_node: Ast.Node.Index,
5489 name_strategy: Inst.NameStrategy,
5490
5491 captures: []const Inst.Capture,
5492 capture_names: []const NullTerminatedString,
5493
5494 decls: []const Inst.Index,
5495
5496 kind: Inst.UnionDecl.Kind,
5497 arg_type: Inst.Ref,
5498
5499 field_names: []const NullTerminatedString,
5500 field_type_body_lens: []const u32,
5501 field_align_body_lens: ?[]const u32,
5502 field_value_body_lens: ?[]const u32,
5503 field_bodies_overlong: []const Inst.Index,
5504
5505 pub fn iterateFields(union_decl: UnwrappedUnionDecl) FieldIterator {
5506 return .{
5507 .next_idx = 0,
5508 .names = union_decl.field_names,
5509 .type_body_lens = union_decl.field_type_body_lens,
5510 .align_body_lens = union_decl.field_align_body_lens,
5511 .value_body_lens = union_decl.field_value_body_lens,
5512 .bodies_overlong = union_decl.field_bodies_overlong,
5513 };
5514 }
5515
5516 pub const FieldIterator = struct {
5517 next_idx: u32,
5518 names: []const NullTerminatedString,
5519 type_body_lens: []const u32,
5520 align_body_lens: ?[]const u32,
5521 value_body_lens: ?[]const u32,
5522 bodies_overlong: []const Inst.Index,
5523 pub const Field = struct {
5524 idx: u32,
5525 name: NullTerminatedString,
5526 type_body: ?[]const Inst.Index,
5527 align_body: ?[]const Inst.Index,
5528 value_body: ?[]const Inst.Index,
5529 };
5530 pub fn next(it: *FieldIterator) ?Field {
5531 const idx = it.next_idx;
5532 if (idx == it.names.len) return null;
5533 it.next_idx += 1;
5534 return .{
5535 .idx = idx,
5536 .name = it.names[idx],
5537 .type_body = it.body(it.type_body_lens[idx]),
5538 .align_body = it.body(if (it.align_body_lens) |l| l[idx] else 0),
5539 .value_body = it.body(if (it.value_body_lens) |l| l[idx] else 0),
5540 };
5541 }
5542 fn body(it: *FieldIterator, len: u32) ?[]const Inst.Index {
5543 if (len == 0) return null;
5544 const b = it.bodies_overlong[0..len];
5545 it.bodies_overlong = it.bodies_overlong[len..];
5546 return b;
5547 }
5548 };
5549};
5550
5551pub fn getEnumDecl(zir: *const Zir, enum_decl: Inst.Index) UnwrappedEnumDecl {
5552 const inst_data = zir.instructions.get(@intFromEnum(enum_decl));
5553 assert(inst_data.tag == .extended);
5554 assert(inst_data.data.extended.opcode == .enum_decl);
5555 const small: Inst.EnumDecl.Small = @bitCast(inst_data.data.extended.small);
5556 const extra = zir.extraData(Inst.EnumDecl, inst_data.data.extended.operand);
5557 var extra_index = extra.end;
5558 const captures_len: u32 = if (small.has_captures_len) blk: {
5559 const captures_len = zir.extra[extra_index];
5560 extra_index += 1;
5561 break :blk captures_len;
5562 } else 0;
5563 const decls_len: u32 = if (small.has_decls_len) blk: {
5564 const decls_len = zir.extra[extra_index];
5565 extra_index += 1;
5566 break :blk decls_len;
5567 } else 0;
5568 const fields_len: u32 = if (small.has_fields_len) blk: {
5569 const fields_len = zir.extra[extra_index];
5570 extra_index += 1;
5571 break :blk fields_len;
5572 } else 0;
5573 const tag_type: Inst.Ref = if (small.has_tag_type) ty: {
5574 const ty = zir.extra[extra_index];
5575 extra_index += 1;
5576 break :ty @enumFromInt(ty);
5577 } else .none;
5578 const captures: []const Inst.Capture = @ptrCast(zir.extra[extra_index..][0..captures_len]);
5579 extra_index += captures_len;
5580 const capture_names: []const NullTerminatedString = @ptrCast(zir.extra[extra_index..][0..captures_len]);
5581 extra_index += captures_len;
5582 const decls: []const Inst.Index = @ptrCast(zir.extra[extra_index..][0..decls_len]);
5583 extra_index += decls_len;
5584 const field_names: []const NullTerminatedString = @ptrCast(zir.extra[extra_index..][0..fields_len]);
5585 extra_index += fields_len;
5586 const field_value_body_lens: ?[]const u32 = if (small.any_field_values) lens: {
5587 const lens = zir.extra[extra_index..][0..fields_len];
5588 extra_index += fields_len;
5589 break :lens @ptrCast(lens);
5590 } else null;
5591 const field_bodies_overlong: []const Inst.Index = @ptrCast(zir.extra[extra_index..]);
5592 return .{
5593 .src_line = extra.data.src_line,
5594 .src_node = extra.data.src_node,
5595 .name_strategy = small.name_strategy,
5596 .captures = captures,
5597 .capture_names = capture_names,
5598 .decls = decls,
5599 .tag_type = tag_type,
5600 .nonexhaustive = small.nonexhaustive,
5601 .field_names = field_names,
5602 .field_value_body_lens = field_value_body_lens,
5603 .field_bodies_overlong = field_bodies_overlong,
5604 };
5605}
5606pub const UnwrappedEnumDecl = struct {
5607 src_line: u32,
5608 src_node: Ast.Node.Index,
5609 name_strategy: Inst.NameStrategy,
5610
5611 captures: []const Inst.Capture,
5612 capture_names: []const NullTerminatedString,
5613
5614 decls: []const Inst.Index,
5615
5616 tag_type: Inst.Ref,
5617 nonexhaustive: bool,
5618
5619 field_names: []const NullTerminatedString,
5620 field_value_body_lens: ?[]const u32,
5621 field_bodies_overlong: []const Inst.Index,
5622
5623 pub fn iterateFields(enum_decl: UnwrappedEnumDecl) FieldIterator {
5624 return .{
5625 .next_idx = 0,
5626 .names = enum_decl.field_names,
5627 .value_body_lens = enum_decl.field_value_body_lens,
5628 .bodies_overlong = enum_decl.field_bodies_overlong,
5629 };
55135630 }
5631
5632 pub const FieldIterator = struct {
5633 next_idx: u32,
5634 names: []const NullTerminatedString,
5635 value_body_lens: ?[]const u32,
5636 bodies_overlong: []const Inst.Index,
5637 pub const Field = struct {
5638 idx: u32,
5639 name: NullTerminatedString,
5640 value_body: ?[]const Inst.Index,
5641 };
5642 pub fn next(it: *FieldIterator) ?Field {
5643 const idx = it.next_idx;
5644 if (idx == it.names.len) return null;
5645 it.next_idx += 1;
5646 return .{
5647 .idx = idx,
5648 .name = it.names[idx],
5649 .value_body = it.body(if (it.value_body_lens) |l| l[idx] else 0),
5650 };
5651 }
5652 fn body(it: *FieldIterator, len: u32) ?[]const Inst.Index {
5653 if (len == 0) return null;
5654 const b = it.bodies_overlong[0..len];
5655 it.bodies_overlong = it.bodies_overlong[len..];
5656 return b;
5657 }
5658 };
5659};
5660
5661pub fn getOpaqueDecl(zir: *const Zir, opaque_decl: Inst.Index) UnwrappedOpaqueDecl {
5662 const inst_data = zir.instructions.get(@intFromEnum(opaque_decl));
5663 assert(inst_data.tag == .extended);
5664 assert(inst_data.data.extended.opcode == .opaque_decl);
5665 const small: Inst.OpaqueDecl.Small = @bitCast(inst_data.data.extended.small);
5666 const extra = zir.extraData(Inst.OpaqueDecl, inst_data.data.extended.operand);
5667 var extra_index = extra.end;
5668 const captures_len: u32 = if (small.has_captures_len) blk: {
5669 const captures_len = zir.extra[extra_index];
5670 extra_index += 1;
5671 break :blk captures_len;
5672 } else 0;
5673 const decls_len: u32 = if (small.has_decls_len) blk: {
5674 const decls_len = zir.extra[extra_index];
5675 extra_index += 1;
5676 break :blk decls_len;
5677 } else 0;
5678 const captures: []const Inst.Capture = @ptrCast(zir.extra[extra_index..][0..captures_len]);
5679 extra_index += captures_len;
5680 const capture_names: []const NullTerminatedString = @ptrCast(zir.extra[extra_index..][0..captures_len]);
5681 extra_index += captures_len;
5682 const decls: []const Inst.Index = @ptrCast(zir.extra[extra_index..][0..decls_len]);
5683 extra_index += decls_len;
5684 return .{
5685 .src_line = extra.data.src_line,
5686 .src_node = extra.data.src_node,
5687 .name_strategy = small.name_strategy,
5688 .captures = captures,
5689 .capture_names = capture_names,
5690 .decls = decls,
5691 };
55145692}
5693pub const UnwrappedOpaqueDecl = struct {
5694 src_line: u32,
5695 src_node: Ast.Node.Index,
5696 name_strategy: Inst.NameStrategy,
5697 captures: []const Inst.Capture,
5698 capture_names: []const NullTerminatedString,
5699 decls: []const Inst.Index,
5700};
src/print_zir.zig+110-425
......@@ -548,10 +548,10 @@ const Writer = struct {
548548 .shl_with_overflow,
549549 => try self.writeOverflowArithmetic(stream, extended),
550550
551 .struct_decl => try self.writeStructDecl(stream, extended),
552 .union_decl => try self.writeUnionDecl(stream, extended),
553 .enum_decl => try self.writeEnumDecl(stream, extended),
554 .opaque_decl => try self.writeOpaqueDecl(stream, extended),
551 .struct_decl => try self.writeStructDecl(stream, inst),
552 .union_decl => try self.writeUnionDecl(stream, inst),
553 .enum_decl => try self.writeEnumDecl(stream, inst),
554 .opaque_decl => try self.writeOpaqueDecl(stream, inst),
555555
556556 .tuple_decl => try self.writeTupleDecl(stream, extended),
557557
......@@ -1427,187 +1427,57 @@ const Writer = struct {
14271427 try self.writeSrcNode(stream, inst_data.src_node);
14281428 }
14291429
1430 fn writeStructDecl(self: *Writer, stream: *std.Io.Writer, extended: Zir.Inst.Extended.InstData) !void {
1431 const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small);
1432
1433 const extra = self.code.extraData(Zir.Inst.StructDecl, extended.operand);
1430 fn writeStructDecl(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void {
1431 const struct_decl = self.code.getStructDecl(inst);
14341432
14351433 const prev_parent_decl_node = self.parent_decl_node;
1436 self.parent_decl_node = extra.data.src_node;
1434 self.parent_decl_node = struct_decl.src_node;
14371435 defer self.parent_decl_node = prev_parent_decl_node;
14381436
1439 const fields_hash: std.zig.SrcHash = @bitCast([4]u32{
1440 extra.data.fields_hash_0,
1441 extra.data.fields_hash_1,
1442 extra.data.fields_hash_2,
1443 extra.data.fields_hash_3,
1444 });
1445
1437 const fields_hash = self.code.getAssociatedSrcHash(inst).?;
14461438 try stream.print("hash({x}) ", .{&fields_hash});
14471439
1448 var extra_index: usize = extra.end;
1449
1450 const captures_len = if (small.has_captures_len) blk: {
1451 const captures_len = self.code.extra[extra_index];
1452 extra_index += 1;
1453 break :blk captures_len;
1454 } else 0;
1455
1456 const fields_len = if (small.has_fields_len) blk: {
1457 const fields_len = self.code.extra[extra_index];
1458 extra_index += 1;
1459 break :blk fields_len;
1460 } else 0;
1461
1462 const decls_len = if (small.has_decls_len) blk: {
1463 const decls_len = self.code.extra[extra_index];
1464 extra_index += 1;
1465 break :blk decls_len;
1466 } else 0;
1467
1468 try self.writeFlag(stream, "known_non_opv, ", small.known_non_opv);
1469 try self.writeFlag(stream, "known_comptime_only, ", small.known_comptime_only);
1470
1471 try stream.print("{s}, ", .{@tagName(small.name_strategy)});
1440 try stream.print("{s}, ", .{@tagName(struct_decl.name_strategy)});
14721441
1473 extra_index = try self.writeCaptures(stream, extra_index, captures_len);
1474 try stream.writeAll(", ");
1475
1476 if (small.has_backing_int) {
1477 const backing_int_body_len = self.code.extra[extra_index];
1478 extra_index += 1;
1442 if (struct_decl.backing_int_type != .none) {
1443 assert(struct_decl.layout == .@"packed");
14791444 try stream.writeAll("packed(");
1480 if (backing_int_body_len == 0) {
1481 const backing_int_ref: Zir.Inst.Ref = @enumFromInt(self.code.extra[extra_index]);
1482 extra_index += 1;
1483 try self.writeInstRef(stream, backing_int_ref);
1484 } else {
1485 const body = self.code.bodySlice(extra_index, backing_int_body_len);
1486 extra_index += backing_int_body_len;
1487 self.indent += 2;
1488 try self.writeBracedDecl(stream, body);
1489 self.indent -= 2;
1490 }
1445 try self.writeInstRef(stream, struct_decl.backing_int_type);
14911446 try stream.writeAll("), ");
14921447 } else {
1493 try stream.print("{s}, ", .{@tagName(small.layout)});
1448 try stream.print("{s}, ", .{@tagName(struct_decl.layout)});
14941449 }
14951450
1496 if (decls_len == 0) {
1497 try stream.writeAll("{}, ");
1498 } else {
1499 try stream.writeAll("{\n");
1500 self.indent += 2;
1501 try self.writeBody(stream, self.code.bodySlice(extra_index, decls_len));
1502 self.indent -= 2;
1503 extra_index += decls_len;
1504 try stream.splatByteAll(' ', self.indent);
1505 try stream.writeAll("}, ");
1506 }
1451 try self.writeCaptures(stream, struct_decl.captures, struct_decl.capture_names);
1452 try stream.writeAll(", ");
1453 try self.writeBracedDecl(stream, struct_decl.decls);
1454 try stream.writeAll(", ");
15071455
1508 if (fields_len == 0) {
1509 try stream.writeAll("{}, {}) ");
1456 if (struct_decl.field_names.len == 0) {
1457 try stream.writeAll("{}) ");
15101458 } else {
1511 const bits_per_field = 4;
1512 const fields_per_u32 = 32 / bits_per_field;
1513 const bit_bags_count = std.math.divCeil(usize, fields_len, fields_per_u32) catch unreachable;
1514 const Field = struct {
1515 type_len: u32 = 0,
1516 align_len: u32 = 0,
1517 init_len: u32 = 0,
1518 type: Zir.Inst.Ref = .none,
1519 name: Zir.NullTerminatedString,
1520 is_comptime: bool,
1521 };
1522 const fields = try self.arena.alloc(Field, fields_len);
1523 {
1524 var bit_bag_index: usize = extra_index;
1525 extra_index += bit_bags_count;
1526 var cur_bit_bag: u32 = undefined;
1527 var field_i: u32 = 0;
1528 while (field_i < fields_len) : (field_i += 1) {
1529 if (field_i % fields_per_u32 == 0) {
1530 cur_bit_bag = self.code.extra[bit_bag_index];
1531 bit_bag_index += 1;
1532 }
1533 const has_align = @as(u1, @truncate(cur_bit_bag)) != 0;
1534 cur_bit_bag >>= 1;
1535 const has_default = @as(u1, @truncate(cur_bit_bag)) != 0;
1536 cur_bit_bag >>= 1;
1537 const is_comptime = @as(u1, @truncate(cur_bit_bag)) != 0;
1538 cur_bit_bag >>= 1;
1539 const has_type_body = @as(u1, @truncate(cur_bit_bag)) != 0;
1540 cur_bit_bag >>= 1;
1541
1542 const field_name_index: Zir.NullTerminatedString = @enumFromInt(self.code.extra[extra_index]);
1543 extra_index += 1;
1544
1545 fields[field_i] = .{
1546 .is_comptime = is_comptime,
1547 .name = field_name_index,
1548 };
1549
1550 if (has_type_body) {
1551 fields[field_i].type_len = self.code.extra[extra_index];
1552 } else {
1553 fields[field_i].type = @enumFromInt(self.code.extra[extra_index]);
1554 }
1555 extra_index += 1;
1556
1557 if (has_align) {
1558 fields[field_i].align_len = self.code.extra[extra_index];
1559 extra_index += 1;
1560 }
1561
1562 if (has_default) {
1563 fields[field_i].init_len = self.code.extra[extra_index];
1564 extra_index += 1;
1565 }
1566 }
1567 }
1568
15691459 try stream.writeAll("{\n");
15701460 self.indent += 2;
15711461
1572 for (fields, 0..) |field, i| {
1462 var it = struct_decl.iterateFields();
1463 while (it.next()) |field| {
15731464 try stream.splatByteAll(' ', self.indent);
15741465 try self.writeFlag(stream, "comptime ", field.is_comptime);
1575 if (field.name != .empty) {
1576 const field_name = self.code.nullTerminatedString(field.name);
1577 try stream.print("{f}: ", .{std.zig.fmtIdP(field_name)});
1578 } else {
1579 try stream.print("@\"{d}\": ", .{i});
1580 }
1581 if (field.type != .none) {
1582 try self.writeInstRef(stream, field.type);
1583 }
1584
1585 if (field.type_len > 0) {
1586 const body = self.code.bodySlice(extra_index, field.type_len);
1587 extra_index += body.len;
1588 self.indent += 2;
1589 try self.writeBracedDecl(stream, body);
1590 self.indent -= 2;
1591 }
1466 const field_name = self.code.nullTerminatedString(field.name);
1467 try stream.print("{f}: ", .{std.zig.fmtIdP(field_name)});
15921468
1593 if (field.align_len > 0) {
1594 const body = self.code.bodySlice(extra_index, field.align_len);
1595 extra_index += body.len;
1596 self.indent += 2;
1469 self.indent += 2;
1470 try self.writeBracedDecl(stream, field.type_body);
1471 if (field.align_body) |body| {
15971472 try stream.writeAll(" align(");
15981473 try self.writeBracedDecl(stream, body);
1599 try stream.writeAll(")");
1600 self.indent -= 2;
1474 try stream.writeByte(')');
16011475 }
1602
1603 if (field.init_len > 0) {
1604 const body = self.code.bodySlice(extra_index, field.init_len);
1605 extra_index += body.len;
1606 self.indent += 2;
1476 if (field.default_body) |body| {
16071477 try stream.writeAll(" = ");
16081478 try self.writeBracedDecl(stream, body);
1609 self.indent -= 2;
16101479 }
1480 self.indent -= 2;
16111481
16121482 try stream.writeAll(",\n");
16131483 }
......@@ -1619,266 +1489,115 @@ const Writer = struct {
16191489 try self.writeSrcNode(stream, .zero);
16201490 }
16211491
1622 fn writeUnionDecl(self: *Writer, stream: *std.Io.Writer, extended: Zir.Inst.Extended.InstData) !void {
1623 const small = @as(Zir.Inst.UnionDecl.Small, @bitCast(extended.small));
1624
1625 const extra = self.code.extraData(Zir.Inst.UnionDecl, extended.operand);
1492 fn writeUnionDecl(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void {
1493 const union_decl = self.code.getUnionDecl(inst);
16261494
16271495 const prev_parent_decl_node = self.parent_decl_node;
1628 self.parent_decl_node = extra.data.src_node;
1496 self.parent_decl_node = union_decl.src_node;
16291497 defer self.parent_decl_node = prev_parent_decl_node;
16301498
1631 const fields_hash: std.zig.SrcHash = @bitCast([4]u32{
1632 extra.data.fields_hash_0,
1633 extra.data.fields_hash_1,
1634 extra.data.fields_hash_2,
1635 extra.data.fields_hash_3,
1636 });
1637
1499 const fields_hash = self.code.getAssociatedSrcHash(inst).?;
16381500 try stream.print("hash({x}) ", .{&fields_hash});
16391501
1640 var extra_index: usize = extra.end;
1641
1642 const tag_type_ref = if (small.has_tag_type) blk: {
1643 const tag_type_ref = @as(Zir.Inst.Ref, @enumFromInt(self.code.extra[extra_index]));
1644 extra_index += 1;
1645 break :blk tag_type_ref;
1646 } else .none;
1647
1648 const captures_len = if (small.has_captures_len) blk: {
1649 const captures_len = self.code.extra[extra_index];
1650 extra_index += 1;
1651 break :blk captures_len;
1652 } else 0;
1653
1654 const body_len = if (small.has_body_len) blk: {
1655 const body_len = self.code.extra[extra_index];
1656 extra_index += 1;
1657 break :blk body_len;
1658 } else 0;
1659
1660 const fields_len = if (small.has_fields_len) blk: {
1661 const fields_len = self.code.extra[extra_index];
1662 extra_index += 1;
1663 break :blk fields_len;
1664 } else 0;
1502 try stream.print("{s}, ", .{@tagName(union_decl.name_strategy)});
16651503
1666 const decls_len = if (small.has_decls_len) blk: {
1667 const decls_len = self.code.extra[extra_index];
1668 extra_index += 1;
1669 break :blk decls_len;
1670 } else 0;
1671
1672 try stream.print("{s}, {s}, ", .{
1673 @tagName(small.name_strategy), @tagName(small.layout),
1674 });
1675 try self.writeFlag(stream, "autoenum, ", small.auto_enum_tag);
1504 switch (union_decl.kind) {
1505 .auto => try stream.writeAll("auto, "),
1506 .@"extern" => try stream.writeAll("extern, "),
1507 .@"packed" => try stream.writeAll("packed, "),
1508 .packed_explicit => {
1509 try stream.writeAll("packed(");
1510 try self.writeInstRef(stream, union_decl.arg_type);
1511 try stream.writeAll("), ");
1512 },
1513 .tagged_explicit => {
1514 try stream.writeAll("auto(");
1515 try self.writeInstRef(stream, union_decl.arg_type);
1516 try stream.writeAll("), ");
1517 },
1518 .tagged_enum => try stream.writeAll("auto(enum)"),
1519 .tagged_enum_explicit => {
1520 try stream.writeAll("auto(enum(");
1521 try self.writeInstRef(stream, union_decl.arg_type);
1522 try stream.writeAll(")), ");
1523 },
1524 }
16761525
1677 extra_index = try self.writeCaptures(stream, extra_index, captures_len);
1526 try self.writeCaptures(stream, union_decl.captures, union_decl.capture_names);
1527 try stream.writeAll(", ");
1528 try self.writeBracedDecl(stream, union_decl.decls);
16781529 try stream.writeAll(", ");
16791530
1680 if (decls_len == 0) {
1681 try stream.writeAll("{}");
1531 if (union_decl.field_names.len == 0) {
1532 try stream.writeAll("}) ");
16821533 } else {
16831534 try stream.writeAll("{\n");
16841535 self.indent += 2;
1685 try self.writeBody(stream, self.code.bodySlice(extra_index, decls_len));
1686 self.indent -= 2;
1687 extra_index += decls_len;
1688 try stream.splatByteAll(' ', self.indent);
1689 try stream.writeAll("}");
1690 }
1691
1692 if (tag_type_ref != .none) {
1693 try stream.writeAll(", ");
1694 try self.writeInstRef(stream, tag_type_ref);
1695 }
1696
1697 if (fields_len == 0) {
1698 try stream.writeAll("}) ");
1699 try self.writeSrcNode(stream, .zero);
1700 return;
1701 }
1702 try stream.writeAll(", ");
17031536
1704 const body = self.code.bodySlice(extra_index, body_len);
1705 extra_index += body.len;
1537 var it = union_decl.iterateFields();
1538 while (it.next()) |field| {
1539 try stream.splatByteAll(' ', self.indent);
1540 const field_name = self.code.nullTerminatedString(field.name);
1541 try stream.print("{f}", .{std.zig.fmtIdP(field_name)});
17061542
1707 try self.writeBracedDecl(stream, body);
1708 try stream.writeAll(", {\n");
1543 self.indent += 2;
1544 if (field.type_body) |body| {
1545 try stream.writeAll(": ");
1546 try self.writeBracedDecl(stream, body);
1547 }
1548 if (field.align_body) |body| {
1549 try stream.writeAll(" align(");
1550 try self.writeBracedDecl(stream, body);
1551 try stream.writeByte(')');
1552 }
1553 if (field.value_body) |body| {
1554 try stream.writeAll(" = ");
1555 try self.writeBracedDecl(stream, body);
1556 }
1557 self.indent -= 2;
17091558
1710 self.indent += 2;
1711 const bits_per_field = 4;
1712 const fields_per_u32 = 32 / bits_per_field;
1713 const bit_bags_count = std.math.divCeil(usize, fields_len, fields_per_u32) catch unreachable;
1714 const body_end = extra_index;
1715 extra_index += bit_bags_count;
1716 var bit_bag_index: usize = body_end;
1717 var cur_bit_bag: u32 = undefined;
1718 var field_i: u32 = 0;
1719 while (field_i < fields_len) : (field_i += 1) {
1720 if (field_i % fields_per_u32 == 0) {
1721 cur_bit_bag = self.code.extra[bit_bag_index];
1722 bit_bag_index += 1;
1559 try stream.writeAll(",\n");
17231560 }
1724 const has_type = @as(u1, @truncate(cur_bit_bag)) != 0;
1725 cur_bit_bag >>= 1;
1726 const has_align = @as(u1, @truncate(cur_bit_bag)) != 0;
1727 cur_bit_bag >>= 1;
1728 const has_value = @as(u1, @truncate(cur_bit_bag)) != 0;
1729 cur_bit_bag >>= 1;
1730 const unused = @as(u1, @truncate(cur_bit_bag)) != 0;
1731 cur_bit_bag >>= 1;
1732
1733 _ = unused;
1734
1735 const field_name_index: Zir.NullTerminatedString = @enumFromInt(self.code.extra[extra_index]);
1736 const field_name = self.code.nullTerminatedString(field_name_index);
1737 extra_index += 1;
1738
1561 self.indent -= 2;
17391562 try stream.splatByteAll(' ', self.indent);
1740 try stream.print("{f}", .{std.zig.fmtIdP(field_name)});
1741
1742 if (has_type) {
1743 const field_type = @as(Zir.Inst.Ref, @enumFromInt(self.code.extra[extra_index]));
1744 extra_index += 1;
1745
1746 try stream.writeAll(": ");
1747 try self.writeInstRef(stream, field_type);
1748 }
1749 if (has_align) {
1750 const align_ref = @as(Zir.Inst.Ref, @enumFromInt(self.code.extra[extra_index]));
1751 extra_index += 1;
1752
1753 try stream.writeAll(" align(");
1754 try self.writeInstRef(stream, align_ref);
1755 try stream.writeAll(")");
1756 }
1757 if (has_value) {
1758 const default_ref = @as(Zir.Inst.Ref, @enumFromInt(self.code.extra[extra_index]));
1759 extra_index += 1;
1760
1761 try stream.writeAll(" = ");
1762 try self.writeInstRef(stream, default_ref);
1763 }
1764 try stream.writeAll(",\n");
1563 try stream.writeAll("}) ");
17651564 }
1766
1767 self.indent -= 2;
1768 try stream.splatByteAll(' ', self.indent);
1769 try stream.writeAll("}) ");
17701565 try self.writeSrcNode(stream, .zero);
17711566 }
17721567
1773 fn writeEnumDecl(self: *Writer, stream: *std.Io.Writer, extended: Zir.Inst.Extended.InstData) !void {
1774 const small = @as(Zir.Inst.EnumDecl.Small, @bitCast(extended.small));
1775
1776 const extra = self.code.extraData(Zir.Inst.EnumDecl, extended.operand);
1568 fn writeEnumDecl(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void {
1569 const enum_decl = self.code.getEnumDecl(inst);
17771570
17781571 const prev_parent_decl_node = self.parent_decl_node;
1779 self.parent_decl_node = extra.data.src_node;
1572 self.parent_decl_node = enum_decl.src_node;
17801573 defer self.parent_decl_node = prev_parent_decl_node;
17811574
1782 const fields_hash: std.zig.SrcHash = @bitCast([4]u32{
1783 extra.data.fields_hash_0,
1784 extra.data.fields_hash_1,
1785 extra.data.fields_hash_2,
1786 extra.data.fields_hash_3,
1787 });
1788
1575 const fields_hash = self.code.getAssociatedSrcHash(inst).?;
17891576 try stream.print("hash({x}) ", .{&fields_hash});
17901577
1791 var extra_index: usize = extra.end;
1792
1793 const tag_type_ref = if (small.has_tag_type) blk: {
1794 const tag_type_ref = @as(Zir.Inst.Ref, @enumFromInt(self.code.extra[extra_index]));
1795 extra_index += 1;
1796 break :blk tag_type_ref;
1797 } else .none;
1798
1799 const captures_len = if (small.has_captures_len) blk: {
1800 const captures_len = self.code.extra[extra_index];
1801 extra_index += 1;
1802 break :blk captures_len;
1803 } else 0;
1804
1805 const body_len = if (small.has_body_len) blk: {
1806 const body_len = self.code.extra[extra_index];
1807 extra_index += 1;
1808 break :blk body_len;
1809 } else 0;
1810
1811 const fields_len = if (small.has_fields_len) blk: {
1812 const fields_len = self.code.extra[extra_index];
1813 extra_index += 1;
1814 break :blk fields_len;
1815 } else 0;
1816
1817 const decls_len = if (small.has_decls_len) blk: {
1818 const decls_len = self.code.extra[extra_index];
1819 extra_index += 1;
1820 break :blk decls_len;
1821 } else 0;
1578 try stream.print("{s}, ", .{@tagName(enum_decl.name_strategy)});
1579 try self.writeFlag(stream, "nonexhaustive, ", enum_decl.nonexhaustive);
1580 try self.writeInstRef(stream, enum_decl.tag_type);
18221581
1823 try stream.print("{s}, ", .{@tagName(small.name_strategy)});
1824 try self.writeFlag(stream, "nonexhaustive, ", small.nonexhaustive);
1825
1826 extra_index = try self.writeCaptures(stream, extra_index, captures_len);
1582 try self.writeCaptures(stream, enum_decl.captures, enum_decl.capture_names);
1583 try stream.writeAll(", ");
1584 try self.writeBracedDecl(stream, enum_decl.decls);
18271585 try stream.writeAll(", ");
18281586
1829 if (decls_len == 0) {
1830 try stream.writeAll("{}, ");
1831 } else {
1832 try stream.writeAll("{\n");
1833 self.indent += 2;
1834 try self.writeBody(stream, self.code.bodySlice(extra_index, decls_len));
1835 self.indent -= 2;
1836 extra_index += decls_len;
1837 try stream.splatByteAll(' ', self.indent);
1838 try stream.writeAll("}, ");
1839 }
1840
1841 if (tag_type_ref != .none) {
1842 try self.writeInstRef(stream, tag_type_ref);
1843 try stream.writeAll(", ");
1844 }
1845
1846 const body = self.code.bodySlice(extra_index, body_len);
1847 extra_index += body.len;
1848
1849 try self.writeBracedDecl(stream, body);
1850 if (fields_len == 0) {
1587 if (enum_decl.field_names.len == 0) {
18511588 try stream.writeAll(", {}) ");
18521589 } else {
18531590 try stream.writeAll(", {\n");
1854
18551591 self.indent += 2;
1856 const bit_bags_count = std.math.divCeil(usize, fields_len, 32) catch unreachable;
1857 const body_end = extra_index;
1858 extra_index += bit_bags_count;
1859 var bit_bag_index: usize = body_end;
1860 var cur_bit_bag: u32 = undefined;
1861 var field_i: u32 = 0;
1862 while (field_i < fields_len) : (field_i += 1) {
1863 if (field_i % 32 == 0) {
1864 cur_bit_bag = self.code.extra[bit_bag_index];
1865 bit_bag_index += 1;
1866 }
1867 const has_tag_value = @as(u1, @truncate(cur_bit_bag)) != 0;
1868 cur_bit_bag >>= 1;
1869
1870 const field_name = self.code.nullTerminatedString(@enumFromInt(self.code.extra[extra_index]));
1871 extra_index += 1;
18721592
1593 var it = enum_decl.iterateFields();
1594 while (it.next()) |field| {
18731595 try stream.splatByteAll(' ', self.indent);
1596 const field_name = self.code.nullTerminatedString(field.name);
18741597 try stream.print("{f}", .{std.zig.fmtIdP(field_name)});
1875
1876 if (has_tag_value) {
1877 const tag_value_ref = @as(Zir.Inst.Ref, @enumFromInt(self.code.extra[extra_index]));
1878 extra_index += 1;
1879
1598 if (field.value_body) |body| {
18801599 try stream.writeAll(" = ");
1881 try self.writeInstRef(stream, tag_value_ref);
1600 try self.writeBracedDecl(stream, body);
18821601 }
18831602 try stream.writeAll(",\n");
18841603 }
......@@ -1889,47 +1608,18 @@ const Writer = struct {
18891608 try self.writeSrcNode(stream, .zero);
18901609 }
18911610
1892 fn writeOpaqueDecl(
1893 self: *Writer,
1894 stream: *std.Io.Writer,
1895 extended: Zir.Inst.Extended.InstData,
1896 ) !void {
1897 const small = @as(Zir.Inst.OpaqueDecl.Small, @bitCast(extended.small));
1898 const extra = self.code.extraData(Zir.Inst.OpaqueDecl, extended.operand);
1611 fn writeOpaqueDecl(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void {
1612 const opaque_decl = self.code.getOpaqueDecl(inst);
18991613
19001614 const prev_parent_decl_node = self.parent_decl_node;
1901 self.parent_decl_node = extra.data.src_node;
1615 self.parent_decl_node = opaque_decl.src_node;
19021616 defer self.parent_decl_node = prev_parent_decl_node;
19031617
1904 var extra_index: usize = extra.end;
1905
1906 const captures_len = if (small.has_captures_len) blk: {
1907 const captures_len = self.code.extra[extra_index];
1908 extra_index += 1;
1909 break :blk captures_len;
1910 } else 0;
1911
1912 const decls_len = if (small.has_decls_len) blk: {
1913 const decls_len = self.code.extra[extra_index];
1914 extra_index += 1;
1915 break :blk decls_len;
1916 } else 0;
1917
1918 try stream.print("{s}, ", .{@tagName(small.name_strategy)});
1919
1920 extra_index = try self.writeCaptures(stream, extra_index, captures_len);
1618 try stream.print("{s}, ", .{@tagName(opaque_decl.name_strategy)});
1619 try self.writeCaptures(stream, opaque_decl.captures, opaque_decl.capture_names);
19211620 try stream.writeAll(", ");
1922
1923 if (decls_len == 0) {
1924 try stream.writeAll("{}) ");
1925 } else {
1926 try stream.writeAll("{\n");
1927 self.indent += 2;
1928 try self.writeBody(stream, self.code.bodySlice(extra_index, decls_len));
1929 self.indent -= 2;
1930 try stream.splatByteAll(' ', self.indent);
1931 try stream.writeAll("}) ");
1932 }
1621 try self.writeBracedDecl(stream, opaque_decl.decls);
1622 try stream.writeAll(") ");
19331623 try self.writeSrcNode(stream, .zero);
19341624 }
19351625
......@@ -2588,14 +2278,11 @@ const Writer = struct {
25882278 return stream.print("%{d}", .{@intFromEnum(inst)});
25892279 }
25902280
2591 fn writeCaptures(self: *Writer, stream: *std.Io.Writer, extra_index: usize, captures_len: u32) !usize {
2592 if (captures_len == 0) {
2593 try stream.writeAll("{}");
2594 return extra_index;
2281 fn writeCaptures(self: *Writer, stream: *std.Io.Writer, captures: []const Zir.Inst.Capture, capture_names: []const Zir.NullTerminatedString) !void {
2282 if (captures.len == 0) {
2283 assert(capture_names.len == 0);
2284 return stream.writeAll("{}");
25952285 }
2596
2597 const captures: []const Zir.Inst.Capture = @ptrCast(self.code.extra[extra_index..][0..captures_len]);
2598 const capture_names: []const Zir.NullTerminatedString = @ptrCast(self.code.extra[extra_index + captures_len ..][0..captures_len]);
25992286 for (captures, capture_names) |capture, name| {
26002287 try stream.writeAll("{ ");
26012288 if (name != .empty) {
......@@ -2604,8 +2291,6 @@ const Writer = struct {
26042291 }
26052292 try self.writeCapture(stream, capture);
26062293 }
2607
2608 return extra_index + 2 * captures_len;
26092294 }
26102295
26112296 fn writeCapture(self: *Writer, stream: *std.Io.Writer, capture: Zir.Inst.Capture) !void {