| ... | @@ -3975,81 +3975,67 @@ fn arrayTypeSentinel(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node. | ... | @@ -3975,81 +3975,67 @@ fn arrayTypeSentinel(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node. |
| 3975 | return rvalue(gz, ri, result, node); | 3975 | return rvalue(gz, ri, result, node); |
| 3976 | } | 3976 | } |
| 3977 | | 3977 | |
| 3978 | const WipMembers = struct { | 3978 | const Scratch = struct { |
| 3979 | payload: *ArrayList(u32), | 3979 | astgen: *AstGen, |
| 3980 | payload_top: usize, | 3980 | scratch_top: u32, |
| 3981 | field_bits_start: u32, | 3981 | fn init(astgen: *AstGen) Scratch { |
| 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); | | |
| 3998 | return .{ | 3982 | return .{ |
| 3999 | .payload = payload, | 3983 | .astgen = astgen, |
| 4000 | .payload_top = payload_top, | 3984 | .scratch_top = @intCast(astgen.scratch.items.len), |
| 4001 | .field_bits_start = field_bits_start, | | |
| 4002 | .fields_start = fields_start, | | |
| 4003 | .fields_end = fields_start, | | |
| 4004 | }; | 3985 | }; |
| 4005 | } | 3986 | } |
| 4006 | | 3987 | fn reset(s: *Scratch) void { |
| 4007 | fn nextDecl(self: *Self, decl_inst: Zir.Inst.Index) void { | 3988 | s.astgen.scratch.shrinkRetainingCapacity(s.scratch_top); |
| 4008 | self.payload.items[self.payload_top + self.decl_index] = @intFromEnum(decl_inst); | 3989 | s.* = undefined; |
| 4009 | self.decl_index += 1; | | |
| 4010 | } | 3990 | } |
| 4011 | | 3991 | fn addSlice(s: *Scratch, len: u32) Allocator.Error!Slice { |
| 4012 | fn nextField(self: *Self, comptime bits_per_field: u32, bits: [bits_per_field]bool) void { | 3992 | const start: u32 = @intCast(s.astgen.scratch.items.len); |
| 4013 | const fields_per_u32 = 32 / bits_per_field; | 3993 | try s.astgen.scratch.resize(s.astgen.gpa, start + len); |
| 4014 | const index = self.field_bits_start + self.field_index / fields_per_u32; | 3994 | return .{ .start = start, .len = len }; |
| 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; | | |
| 4024 | } | 3995 | } |
| 4025 | | 3996 | fn addOptionalSlice(s: *Scratch, present: bool, len: u32) Allocator.Error!?Slice { |
| 4026 | fn appendToField(self: *Self, data: u32) void { | 3997 | if (!present) return null; |
| 4027 | assert(self.fields_end < self.payload.items.len); | 3998 | return try addSlice(s, len); |
| 4028 | self.payload.items[self.fields_end] = data; | | |
| 4029 | self.fields_end += 1; | | |
| 4030 | } | 3999 | } |
| 4031 | | 4000 | fn appendBodyWithFixups(s: *Scratch, body: []const Zir.Inst.Index) Allocator.Error!u32 { |
| 4032 | fn finishBits(self: *Self, comptime bits_per_field: u32) void { | 4001 | const len = countBodyLenAfterFixups(s.astgen, body); |
| 4033 | if (bits_per_field > 0) { | 4002 | try s.astgen.scratch.ensureUnusedCapacity(s.astgen.gpa, len); |
| 4034 | const fields_per_u32 = 32 / bits_per_field; | 4003 | appendBodyWithFixupsArrayList(s.astgen, &s.astgen.scratch, body); |
| 4035 | const empty_field_slots = fields_per_u32 - (self.field_index % fields_per_u32); | 4004 | return len; |
| 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 | } | | |
| 4041 | } | 4005 | } |
| 4042 | | 4006 | /// Returns the slice containing all data added to this `Scratch`. |
| 4043 | fn declsSlice(self: *Self) []u32 { | 4007 | fn all(s: *Scratch) Slice { |
| 4044 | return self.payload.items[self.payload_top..][0..self.decl_index]; | 4008 | const len = s.astgen.scratch.items.len - s.scratch_top; |
| | 4009 | return .{ .start = s.scratch_top, .len = @intCast(len) }; |
| 4045 | } | 4010 | } |
| | 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 | }; |
| 4046 | | 4019 | |
| 4047 | fn fieldsSlice(self: *Self) []u32 { | 4020 | const WipDecls = struct { |
| 4048 | return self.payload.items[self.field_bits_start..self.fields_end]; | 4021 | astgen: *AstGen, |
| 4049 | } | 4022 | slice: Scratch.Slice, |
| | 4023 | index: u32, |
| 4050 | | 4024 | |
| 4051 | fn deinit(self: *Self) void { | 4025 | fn init(scratch: *Scratch, decls_len: u32) Allocator.Error!WipDecls { |
| 4052 | self.payload.items.len = self.payload_top; | 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; |
| 4053 | } | 4039 | } |
| 4054 | }; | 4040 | }; |
| 4055 | | 4041 | |
| ... | @@ -4057,7 +4043,7 @@ fn fnDecl( | ... | @@ -4057,7 +4043,7 @@ fn fnDecl( |
| 4057 | astgen: *AstGen, | 4043 | astgen: *AstGen, |
| 4058 | gz: *GenZir, | 4044 | gz: *GenZir, |
| 4059 | scope: *Scope, | 4045 | scope: *Scope, |
| 4060 | wip_members: *WipMembers, | 4046 | wip_decls: *WipDecls, |
| 4061 | decl_node: Ast.Node.Index, | 4047 | decl_node: Ast.Node.Index, |
| 4062 | body_node: Ast.Node.OptionalIndex, | 4048 | body_node: Ast.Node.OptionalIndex, |
| 4063 | fn_proto: Ast.full.FnProto, | 4049 | fn_proto: Ast.full.FnProto, |
| ... | @@ -4133,7 +4119,7 @@ fn fnDecl( | ... | @@ -4133,7 +4119,7 @@ fn fnDecl( |
| 4133 | assert(!is_extern); // validated by parser (TODO why???) | 4119 | assert(!is_extern); // validated by parser (TODO why???) |
| 4134 | } | 4120 | } |
| 4135 | | 4121 | |
| 4136 | wip_members.nextDecl(decl_inst); | 4122 | wip_decls.nextDecl(decl_inst); |
| 4137 | | 4123 | |
| 4138 | var type_gz: GenZir = .{ | 4124 | var type_gz: GenZir = .{ |
| 4139 | .is_comptime = true, | 4125 | .is_comptime = true, |
| ... | @@ -4488,7 +4474,7 @@ fn globalVarDecl( | ... | @@ -4488,7 +4474,7 @@ fn globalVarDecl( |
| 4488 | astgen: *AstGen, | 4474 | astgen: *AstGen, |
| 4489 | gz: *GenZir, | 4475 | gz: *GenZir, |
| 4490 | scope: *Scope, | 4476 | scope: *Scope, |
| 4491 | wip_members: *WipMembers, | 4477 | wip_decls: *WipDecls, |
| 4492 | node: Ast.Node.Index, | 4478 | node: Ast.Node.Index, |
| 4493 | var_decl: Ast.full.VarDecl, | 4479 | var_decl: Ast.full.VarDecl, |
| 4494 | ) InnerError!void { | 4480 | ) InnerError!void { |
| ... | @@ -4533,7 +4519,7 @@ fn globalVarDecl( | ... | @@ -4533,7 +4519,7 @@ fn globalVarDecl( |
| 4533 | const decl_column = astgen.source_column; | 4519 | const decl_column = astgen.source_column; |
| 4534 | | 4520 | |
| 4535 | const decl_inst = try gz.makeDeclaration(node); | 4521 | const decl_inst = try gz.makeDeclaration(node); |
| 4536 | wip_members.nextDecl(decl_inst); | 4522 | wip_decls.nextDecl(decl_inst); |
| 4537 | | 4523 | |
| 4538 | if (var_decl.ast.init_node.unwrap()) |init_node| { | 4524 | if (var_decl.ast.init_node.unwrap()) |init_node| { |
| 4539 | if (is_extern) { | 4525 | if (is_extern) { |
| ... | @@ -4635,7 +4621,7 @@ fn comptimeDecl( | ... | @@ -4635,7 +4621,7 @@ fn comptimeDecl( |
| 4635 | astgen: *AstGen, | 4621 | astgen: *AstGen, |
| 4636 | gz: *GenZir, | 4622 | gz: *GenZir, |
| 4637 | scope: *Scope, | 4623 | scope: *Scope, |
| 4638 | wip_members: *WipMembers, | 4624 | wip_decls: *WipDecls, |
| 4639 | node: Ast.Node.Index, | 4625 | node: Ast.Node.Index, |
| 4640 | ) InnerError!void { | 4626 | ) InnerError!void { |
| 4641 | const tree = astgen.tree; | 4627 | const tree = astgen.tree; |
| ... | @@ -4650,7 +4636,7 @@ fn comptimeDecl( | ... | @@ -4650,7 +4636,7 @@ fn comptimeDecl( |
| 4650 | // Up top so the ZIR instruction index marks the start range of this | 4636 | // Up top so the ZIR instruction index marks the start range of this |
| 4651 | // top-level declaration. | 4637 | // top-level declaration. |
| 4652 | const decl_inst = try gz.makeDeclaration(node); | 4638 | const decl_inst = try gz.makeDeclaration(node); |
| 4653 | wip_members.nextDecl(decl_inst); | 4639 | wip_decls.nextDecl(decl_inst); |
| 4654 | astgen.advanceSourceCursorToNode(node); | 4640 | astgen.advanceSourceCursorToNode(node); |
| 4655 | | 4641 | |
| 4656 | // This is just needed for the `setDeclaration` call. | 4642 | // This is just needed for the `setDeclaration` call. |
| ... | @@ -4698,7 +4684,7 @@ fn testDecl( | ... | @@ -4698,7 +4684,7 @@ fn testDecl( |
| 4698 | astgen: *AstGen, | 4684 | astgen: *AstGen, |
| 4699 | gz: *GenZir, | 4685 | gz: *GenZir, |
| 4700 | scope: *Scope, | 4686 | scope: *Scope, |
| 4701 | wip_members: *WipMembers, | 4687 | wip_decls: *WipDecls, |
| 4702 | node: Ast.Node.Index, | 4688 | node: Ast.Node.Index, |
| 4703 | ) InnerError!void { | 4689 | ) InnerError!void { |
| 4704 | const tree = astgen.tree; | 4690 | const tree = astgen.tree; |
| ... | @@ -4714,7 +4700,7 @@ fn testDecl( | ... | @@ -4714,7 +4700,7 @@ fn testDecl( |
| 4714 | // top-level declaration. | 4700 | // top-level declaration. |
| 4715 | const decl_inst = try gz.makeDeclaration(node); | 4701 | const decl_inst = try gz.makeDeclaration(node); |
| 4716 | | 4702 | |
| 4717 | wip_members.nextDecl(decl_inst); | 4703 | wip_decls.nextDecl(decl_inst); |
| 4718 | astgen.advanceSourceCursorToNode(node); | 4704 | astgen.advanceSourceCursorToNode(node); |
| 4719 | | 4705 | |
| 4720 | // This is just needed for the `setDeclaration` call. | 4706 | // This is just needed for the `setDeclaration` call. |
| ... | @@ -4914,7 +4900,7 @@ fn structDeclInner( | ... | @@ -4914,7 +4900,7 @@ fn structDeclInner( |
| 4914 | node: Ast.Node.Index, | 4900 | node: Ast.Node.Index, |
| 4915 | container_decl: Ast.full.ContainerDecl, | 4901 | container_decl: Ast.full.ContainerDecl, |
| 4916 | layout: std.builtin.Type.ContainerLayout, | 4902 | layout: std.builtin.Type.ContainerLayout, |
| 4917 | backing_int_node: Ast.Node.OptionalIndex, | 4903 | maybe_backing_int_node: Ast.Node.OptionalIndex, |
| 4918 | name_strat: Zir.Inst.NameStrategy, | 4904 | name_strat: Zir.Inst.NameStrategy, |
| 4919 | ) InnerError!Zir.Inst.Ref { | 4905 | ) InnerError!Zir.Inst.Ref { |
| 4920 | const astgen = gz.astgen; | 4906 | const astgen = gz.astgen; |
| ... | @@ -4930,27 +4916,39 @@ fn structDeclInner( | ... | @@ -4930,27 +4916,39 @@ fn structDeclInner( |
| 4930 | if (node == .root) { | 4916 | if (node == .root) { |
| 4931 | return astgen.failNode(tuple_field_node, "file cannot be a tuple", .{}); | 4917 | return astgen.failNode(tuple_field_node, "file cannot be a tuple", .{}); |
| 4932 | } else { | 4918 | } 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); |
| 4934 | } | 4920 | } |
| 4935 | } | 4921 | } |
| 4936 | | 4922 | |
| | 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 | |
| 4937 | const decl_inst = try gz.reserveInstructionIndex(); | 4935 | const decl_inst = try gz.reserveInstructionIndex(); |
| 4938 | | 4936 | |
| 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) { |
| 4940 | try gz.setStruct(decl_inst, .{ | 4938 | try gz.setStruct(decl_inst, .{ |
| 4941 | .src_node = node, | 4939 | .src_node = node, |
| | 4940 | .name_strat = name_strat, |
| 4942 | .layout = layout, | 4941 | .layout = layout, |
| 4943 | .captures_len = 0, | 4942 | .backing_int_type = .none, |
| 4944 | .fields_len = 0, | | |
| 4945 | .decls_len = 0, | 4943 | .decls_len = 0, |
| 4946 | .has_backing_int = false, | 4944 | .fields_len = 0, |
| 4947 | .known_non_opv = false, | 4945 | .any_field_aligns = false, |
| 4948 | .known_comptime_only = false, | 4946 | .any_field_defaults = false, |
| 4949 | .any_comptime_fields = false, | 4947 | .any_comptime_fields = false, |
| 4950 | .any_default_inits = false, | 4948 | .fields_hash = @splat(0), |
| 4951 | .any_aligned_fields = false, | 4949 | .captures = &.{}, |
| 4952 | .fields_hash = std.zig.hashSrc(@tagName(layout)), | 4950 | .capture_names = &.{}, |
| 4953 | .name_strat = name_strat, | 4951 | .remaining = &.{}, |
| 4954 | }); | 4952 | }); |
| 4955 | return decl_inst.toRef(); | 4953 | return decl_inst.toRef(); |
| 4956 | } | 4954 | } |
| ... | @@ -4967,7 +4965,6 @@ fn structDeclInner( | ... | @@ -4967,7 +4965,6 @@ fn structDeclInner( |
| 4967 | // The struct_decl instruction introduces a scope in which the decls of the struct | 4965 | // The struct_decl instruction introduces a scope in which the decls of the struct |
| 4968 | // are in scope, so that field types, alignments, and default value expressions | 4966 | // are in scope, so that field types, alignments, and default value expressions |
| 4969 | // can refer to decls within the struct itself. | 4967 | // can refer to decls within the struct itself. |
| 4970 | astgen.advanceSourceCursorToNode(node); | | |
| 4971 | var block_scope: GenZir = .{ | 4968 | var block_scope: GenZir = .{ |
| 4972 | .parent = &namespace.base, | 4969 | .parent = &namespace.base, |
| 4973 | .decl_node_index = node, | 4970 | .decl_node_index = node, |
| ... | @@ -4979,197 +4976,118 @@ fn structDeclInner( | ... | @@ -4979,197 +4976,118 @@ fn structDeclInner( |
| 4979 | }; | 4976 | }; |
| 4980 | defer block_scope.unstack(); | 4977 | defer block_scope.unstack(); |
| 4981 | | 4978 | |
| 4982 | const scratch_top = astgen.scratch.items.len; | 4979 | const scan_result = try astgen.scanContainer(&namespace, container_decl.ast.members, .@"struct"); |
| 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 | }; | | |
| 5010 | | 4980 | |
| 5011 | const decl_count = try astgen.scanContainer(&namespace, container_decl.ast.members, .@"struct"); | 4981 | var scratch: Scratch = .init(astgen); |
| 5012 | const field_count: u32 = @intCast(container_decl.ast.members.len - decl_count); | 4982 | defer scratch.reset(); |
| 5013 | | 4983 | |
| 5014 | const bits_per_field = 4; | 4984 | // Replicate the structure of the ZIR trailing data in `scratch` |
| 5015 | const max_field_size = 5; | 4985 | var wip_decls: WipDecls = try .init(&scratch, scan_result.decls_len); |
| 5016 | var wip_members = try WipMembers.init(gpa, &astgen.scratch, decl_count, field_count, bits_per_field, max_field_size); | 4986 | const field_names = try scratch.addSlice(scan_result.fields_len); |
| 5017 | defer wip_members.deinit(); | 4987 | const field_type_body_lens = try scratch.addSlice(scan_result.fields_len); |
| 5018 | | 4988 | const field_align_body_lens = try scratch.addOptionalSlice(scan_result.any_field_aligns, scan_result.fields_len); |
| 5019 | // We will use the scratch buffer, starting here, for the bodies: | 4989 | const field_default_body_lens = try scratch.addOptionalSlice(scan_result.any_field_values, scan_result.fields_len); |
| 5020 | // bodies: { // for every fields_len | 4990 | const field_comptime_bits = try scratch.addOptionalSlice( |
| 5021 | // field_type_body_inst: Inst, // for each field_type_body_len | 4991 | scan_result.any_comptime_fields, |
| 5022 | // align_body_inst: Inst, // for each align_body_len | 4992 | std.math.divCeil(u32, scan_result.fields_len, 32) catch unreachable, |
| 5023 | // init_body_inst: Inst, // for each init_body_len | 4993 | ); |
| 5024 | // } | 4994 | if (field_comptime_bits) |bits| @memset(bits.get(astgen), 0); |
| 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; | | |
| 5031 | | 4995 | |
| 5032 | const old_hasher = astgen.src_hasher; | 4996 | const old_hasher = astgen.src_hasher; |
| 5033 | defer astgen.src_hasher = old_hasher; | 4997 | defer astgen.src_hasher = old_hasher; |
| 5034 | astgen.src_hasher = std.zig.SrcHasher.init(.{}); | 4998 | astgen.src_hasher = .init(.{}); |
| 5035 | astgen.src_hasher.update(@tagName(layout)); | | |
| 5036 | if (backing_int_node.unwrap()) |arg| { | | |
| 5037 | astgen.src_hasher.update(tree.getNodeSource(arg)); | | |
| 5038 | } | | |
| 5039 | | 4999 | |
| 5040 | var known_non_opv = false; | 5000 | var next_field_idx: u32 = 0; |
| 5041 | var known_comptime_only = false; | | |
| 5042 | var any_comptime_fields = false; | | |
| 5043 | var any_aligned_fields = false; | | |
| 5044 | var any_default_inits = false; | | |
| 5045 | for (container_decl.ast.members) |member_node| { | 5001 | 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)) { |
| 5047 | .decl => continue, | 5003 | .decl => continue, |
| 5048 | .field => |field| field, | 5004 | .field => |field| field, |
| 5049 | }; | 5005 | }; |
| | 5006 | const field_idx = next_field_idx; |
| | 5007 | next_field_idx += 1; |
| 5050 | | 5008 | |
| 5051 | astgen.src_hasher.update(tree.getNodeSource(member_node)); | 5009 | astgen.src_hasher.update(tree.getNodeSource(member_node)); |
| 5052 | | 5010 | |
| 5053 | const field_name = try astgen.identAsString(member.ast.main_token); | | |
| 5054 | member.convertToNonTupleLike(astgen.tree); | 5011 | member.convertToNonTupleLike(astgen.tree); |
| 5055 | assert(!member.ast.tuple_like); | 5012 | 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; | | |
| 5067 | | 5013 | |
| 5068 | if (is_comptime) { | 5014 | field_names.get(astgen)[field_idx] = @intFromEnum(try astgen.identAsString(member.ast.main_token)); |
| 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 }); | | |
| 5080 | | 5015 | |
| 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); |
| 5082 | if (!block_scope.endsWithNoReturn()) { | 5021 | 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); |
| 5084 | } | 5023 | } |
| 5085 | const body = block_scope.instructionsSlice(); | 5024 | const body_len = try scratch.appendBodyWithFixups(block_scope.instructionsSlice()); |
| 5086 | const old_scratch_len = astgen.scratch.items.len; | 5025 | field_type_body_lens.get(astgen)[field_idx] = body_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)); | | |
| 5090 | block_scope.instructions.items.len = block_scope.instructions_top; | 5026 | block_scope.instructions.items.len = block_scope.instructions_top; |
| 5091 | } else { | | |
| 5092 | wip_members.appendToField(@intFromEnum(field_type)); | | |
| 5093 | } | 5027 | } |
| 5094 | | 5028 | |
| 5095 | if (member.ast.align_expr.unwrap()) |align_expr| { | 5029 | if (member.ast.align_expr.unwrap()) |align_node| { |
| 5096 | if (layout == .@"packed") { | 5030 | 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", .{}); |
| 5098 | } | 5032 | } |
| 5099 | any_aligned_fields = true; | 5033 | const align_ref = try expr(&block_scope, &namespace.base, coerced_align_ri, align_node); |
| 5100 | const align_ref = try expr(&block_scope, &namespace.base, coerced_align_ri, align_expr); | | |
| 5101 | if (!block_scope.endsWithNoReturn()) { | 5034 | if (!block_scope.endsWithNoReturn()) { |
| 5102 | _ = try block_scope.addBreak(.break_inline, decl_inst, align_ref); | 5035 | _ = try block_scope.addBreak(.break_inline, decl_inst, align_ref); |
| 5103 | } | 5036 | } |
| 5104 | const body = block_scope.instructionsSlice(); | 5037 | const body_len = try scratch.appendBodyWithFixups(block_scope.instructionsSlice()); |
| 5105 | const old_scratch_len = astgen.scratch.items.len; | 5038 | field_align_body_lens.?.get(astgen)[field_idx] = body_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)); | | |
| 5109 | block_scope.instructions.items.len = block_scope.instructions_top; | 5039 | block_scope.instructions.items.len = block_scope.instructions_top; |
| | 5040 | } else if (field_align_body_lens) |lens| { |
| | 5041 | lens.get(astgen)[field_idx] = 0; |
| 5110 | } | 5042 | } |
| 5111 | | 5043 | |
| 5112 | if (member.ast.value_expr.unwrap()) |value_expr| { | 5044 | if (member.ast.value_expr.unwrap()) |default_node| { |
| 5113 | any_default_inits = true; | 5045 | const ri: ResultInfo = .{ .rl = .{ .coerced_ty = decl_inst.toRef() } }; |
| 5114 | | 5046 | const default_ref = try expr(&block_scope, &namespace.base, ri, default_node); |
| 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); | | |
| 5120 | if (!block_scope.endsWithNoReturn()) { | 5047 | 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); |
| 5122 | } | 5049 | } |
| 5123 | const body = block_scope.instructionsSlice(); | 5050 | const body_len = try scratch.appendBodyWithFixups(block_scope.instructionsSlice()); |
| 5124 | const old_scratch_len = astgen.scratch.items.len; | 5051 | field_default_body_lens.?.get(astgen)[field_idx] = body_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)); | | |
| 5128 | block_scope.instructions.items.len = block_scope.instructions_top; | 5052 | block_scope.instructions.items.len = block_scope.instructions_top; |
| 5129 | } else if (member.comptime_token) |comptime_token| { | 5053 | } else if (field_default_body_lens) |lens| { |
| 5130 | return astgen.failTok(comptime_token, "comptime field without default initialization value", .{}); | 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; |
| 5131 | } | 5067 | } |
| 5132 | } | 5068 | } |
| | 5069 | assert(next_field_idx == scan_result.fields_len); |
| | 5070 | wip_decls.finish(); |
| 5133 | | 5071 | |
| 5134 | var fields_hash: std.zig.SrcHash = undefined; | 5072 | var fields_hash: std.zig.SrcHash = undefined; |
| 5135 | astgen.src_hasher.final(&fields_hash); | 5073 | astgen.src_hasher.final(&fields_hash); |
| 5136 | | 5074 | |
| 5137 | try gz.setStruct(decl_inst, .{ | 5075 | try gz.setStruct(decl_inst, .{ |
| 5138 | .src_node = node, | 5076 | .src_node = node, |
| | 5077 | .name_strat = name_strat, |
| 5139 | .layout = layout, | 5078 | .layout = layout, |
| 5140 | .captures_len = @intCast(namespace.captures.count()), | 5079 | .backing_int_type = backing_int_type_ref, |
| 5141 | .fields_len = field_count, | 5080 | .decls_len = scan_result.decls_len, |
| 5142 | .decls_len = decl_count, | 5081 | .fields_len = scan_result.fields_len, |
| 5143 | .has_backing_int = backing_int_ref != .none, | 5082 | .any_field_aligns = scan_result.any_field_aligns, |
| 5144 | .known_non_opv = known_non_opv, | 5083 | .any_field_defaults = scan_result.any_field_values, |
| 5145 | .known_comptime_only = known_comptime_only, | 5084 | .any_comptime_fields = scan_result.any_comptime_fields, |
| 5146 | .any_comptime_fields = any_comptime_fields, | | |
| 5147 | .any_default_inits = any_default_inits, | | |
| 5148 | .any_aligned_fields = any_aligned_fields, | | |
| 5149 | .fields_hash = fields_hash, | 5085 | .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), |
| 5151 | }); | 5089 | }); |
| 5152 | | 5090 | |
| 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 | | | |
| 5173 | block_scope.unstack(); | 5091 | block_scope.unstack(); |
| 5174 | return decl_inst.toRef(); | 5092 | return decl_inst.toRef(); |
| 5175 | } | 5093 | } |
| ... | @@ -5281,11 +5199,34 @@ fn unionDeclInner( | ... | @@ -5281,11 +5199,34 @@ fn unionDeclInner( |
| 5281 | auto_enum_tok: ?Ast.TokenIndex, | 5199 | auto_enum_tok: ?Ast.TokenIndex, |
| 5282 | name_strat: Zir.Inst.NameStrategy, | 5200 | name_strat: Zir.Inst.NameStrategy, |
| 5283 | ) InnerError!Zir.Inst.Ref { | 5201 | ) InnerError!Zir.Inst.Ref { |
| 5284 | const decl_inst = try gz.reserveInstructionIndex(); | | |
| 5285 | | | |
| 5286 | const astgen = gz.astgen; | 5202 | const astgen = gz.astgen; |
| 5287 | const gpa = astgen.gpa; | 5203 | const gpa = astgen.gpa; |
| 5288 | | 5204 | |
| | 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 | |
| 5289 | var namespace: Scope.Namespace = .{ | 5230 | var namespace: Scope.Namespace = .{ |
| 5290 | .parent = scope, | 5231 | .parent = scope, |
| 5291 | .node = node, | 5232 | .node = node, |
| ... | @@ -5298,7 +5239,6 @@ fn unionDeclInner( | ... | @@ -5298,7 +5239,6 @@ fn unionDeclInner( |
| 5298 | // The union_decl instruction introduces a scope in which the decls of the union | 5239 | // The union_decl instruction introduces a scope in which the decls of the union |
| 5299 | // are in scope, so that field types, alignments, and default value expressions | 5240 | // are in scope, so that field types, alignments, and default value expressions |
| 5300 | // can refer to decls within the union itself. | 5241 | // can refer to decls within the union itself. |
| 5301 | astgen.advanceSourceCursorToNode(node); | | |
| 5302 | var block_scope: GenZir = .{ | 5242 | var block_scope: GenZir = .{ |
| 5303 | .parent = &namespace.base, | 5243 | .parent = &namespace.base, |
| 5304 | .decl_node_index = node, | 5244 | .decl_node_index = node, |
| ... | @@ -5310,42 +5250,31 @@ fn unionDeclInner( | ... | @@ -5310,42 +5250,31 @@ fn unionDeclInner( |
| 5310 | }; | 5250 | }; |
| 5311 | defer block_scope.unstack(); | 5251 | defer block_scope.unstack(); |
| 5312 | | 5252 | |
| 5313 | const decl_count = try astgen.scanContainer(&namespace, members, .@"union"); | 5253 | const scan_result = 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 | } | | |
| 5323 | | 5254 | |
| 5324 | const arg_inst: Zir.Inst.Ref = if (opt_arg_node.unwrap()) |arg_node| | 5255 | var scratch: Scratch = .init(astgen); |
| 5325 | try typeExpr(&block_scope, &namespace.base, arg_node) | 5256 | defer scratch.reset(); |
| 5326 | else | | |
| 5327 | .none; | | |
| 5328 | | 5257 | |
| 5329 | const bits_per_field = 4; | 5258 | // Replicate the structure of the ZIR trailing data in `scratch` |
| 5330 | const max_field_size = 4; | 5259 | var wip_decls: WipDecls = try .init(&scratch, scan_result.decls_len); |
| 5331 | var any_aligned_fields = false; | 5260 | const field_names = try scratch.addSlice(scan_result.fields_len); |
| 5332 | var wip_members = try WipMembers.init(gpa, &astgen.scratch, decl_count, field_count, bits_per_field, max_field_size); | 5261 | const field_type_body_lens = try scratch.addSlice(scan_result.fields_len); |
| 5333 | defer wip_members.deinit(); | 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); |
| 5334 | | 5264 | |
| 5335 | const old_hasher = astgen.src_hasher; | 5265 | const old_hasher = astgen.src_hasher; |
| 5336 | defer astgen.src_hasher = old_hasher; | 5266 | defer astgen.src_hasher = old_hasher; |
| 5337 | astgen.src_hasher = std.zig.SrcHasher.init(.{}); | 5267 | astgen.src_hasher = .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 | } | | |
| 5343 | | 5268 | |
| | 5269 | var next_field_idx: u32 = 0; |
| 5344 | for (members) |member_node| { | 5270 | 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)) { |
| 5346 | .decl => continue, | 5272 | .decl => continue, |
| 5347 | .field => |field| field, | 5273 | .field => |field| field, |
| 5348 | }; | 5274 | }; |
| | 5275 | const field_idx = next_field_idx; |
| | 5276 | next_field_idx += 1; |
| | 5277 | |
| 5349 | astgen.src_hasher.update(astgen.tree.getNodeSource(member_node)); | 5278 | astgen.src_hasher.update(astgen.tree.getNodeSource(member_node)); |
| 5350 | member.convertToNonTupleLike(astgen.tree); | 5279 | member.convertToNonTupleLike(astgen.tree); |
| 5351 | if (member.ast.tuple_like) { | 5280 | if (member.ast.tuple_like) { |
| ... | @@ -5355,97 +5284,91 @@ fn unionDeclInner( | ... | @@ -5355,97 +5284,91 @@ fn unionDeclInner( |
| 5355 | return astgen.failTok(comptime_token, "union fields cannot be marked comptime", .{}); | 5284 | return astgen.failTok(comptime_token, "union fields cannot be marked comptime", .{}); |
| 5356 | } | 5285 | } |
| 5357 | | 5286 | |
| 5358 | const field_name = try astgen.identAsString(member.ast.main_token); | 5287 | field_names.get(astgen)[field_idx] = @intFromEnum(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 }); | | |
| 5366 | | 5288 | |
| 5367 | if (member.ast.type_expr.unwrap()) |type_expr| { | 5289 | if (member.ast.type_expr.unwrap()) |type_node| { |
| 5368 | const field_type = try typeExpr(&block_scope, &namespace.base, type_expr); | 5290 | const type_ref = try typeExpr(&block_scope, &namespace.base, type_node); |
| 5369 | wip_members.appendToField(@intFromEnum(field_type)); | 5291 | if (!block_scope.endsWithNoReturn()) { |
| 5370 | } else if (arg_inst == .none and auto_enum_tok == null) { | 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) { |
| 5371 | return astgen.failNode(member_node, "union field missing type", .{}); | 5298 | return astgen.failNode(member_node, "union field missing type", .{}); |
| | 5299 | } else { |
| | 5300 | field_type_body_lens.get(astgen)[field_idx] = 0; |
| 5372 | } | 5301 | } |
| 5373 | if (member.ast.align_expr.unwrap()) |align_expr| { | 5302 | |
| | 5303 | if (member.ast.align_expr.unwrap()) |align_node| { |
| 5374 | if (layout == .@"packed") { | 5304 | 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", .{}); |
| 5376 | } | 5306 | } |
| 5377 | const align_inst = try expr(&block_scope, &block_scope.base, coerced_align_ri, align_expr); | 5307 | const align_ref = try expr(&block_scope, &namespace.base, coerced_align_ri, align_node); |
| 5378 | wip_members.appendToField(@intFromEnum(align_inst)); | 5308 | if (!block_scope.endsWithNoReturn()) { |
| 5379 | any_aligned_fields = true; | 5309 | _ = try block_scope.addBreak(.break_inline, decl_inst, align_ref); |
| 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 | ); | | |
| 5395 | } | 5310 | } |
| 5396 | if (auto_enum_tok == null) { | 5311 | const body_len = try scratch.appendBodyWithFixups(block_scope.instructionsSlice()); |
| 5397 | return astgen.failNodeNotes( | 5312 | field_align_body_lens.?.get(astgen)[field_idx] = body_len; |
| 5398 | node, | 5313 | block_scope.instructions.items.len = block_scope.instructions_top; |
| 5399 | "explicitly valued tagged union requires inferred enum tag type", | 5314 | } else if (field_align_body_lens) |lens| { |
| 5400 | .{}, | 5315 | lens.get(astgen)[field_idx] = 0; |
| 5401 | &[_]u32{ | 5316 | } |
| 5402 | try astgen.errNoteNode( | 5317 | |
| 5403 | value_expr, | 5318 | if (member.ast.value_expr.unwrap()) |value_node| { |
| 5404 | "tag value specified here", | 5319 | if (!explicit_int_or_enum_tag) return astgen.failNodeNotes( |
| 5405 | .{}, | 5320 | node, |
| 5406 | ), | 5321 | "explicitly valued tagged union missing integer tag type", |
| 5407 | }, | 5322 | .{}, |
| 5408 | ); | 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); |
| 5409 | } | 5335 | } |
| 5410 | const tag_value = try expr(&block_scope, &block_scope.base, .{ .rl = .{ .ty = arg_inst } }, value_expr); | 5336 | const body_len = try scratch.appendBodyWithFixups(block_scope.instructionsSlice()); |
| 5411 | wip_members.appendToField(@intFromEnum(tag_value)); | 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; |
| 5412 | } | 5341 | } |
| 5413 | } | 5342 | } |
| | 5343 | assert(next_field_idx == scan_result.fields_len); |
| | 5344 | wip_decls.finish(); |
| 5414 | | 5345 | |
| 5415 | var fields_hash: std.zig.SrcHash = undefined; | 5346 | var fields_hash: std.zig.SrcHash = undefined; |
| 5416 | astgen.src_hasher.final(&fields_hash); | 5347 | astgen.src_hasher.final(&fields_hash); |
| 5417 | | 5348 | |
| 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 | | | |
| 5425 | try gz.setUnion(decl_inst, .{ | 5349 | try gz.setUnion(decl_inst, .{ |
| 5426 | .src_node = node, | 5350 | .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, | | |
| 5436 | .name_strat = name_strat, | 5351 | .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), |
| 5437 | }); | 5370 | }); |
| 5438 | | 5371 | |
| 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 | | | |
| 5449 | block_scope.unstack(); | 5372 | block_scope.unstack(); |
| 5450 | return decl_inst.toRef(); | 5373 | return decl_inst.toRef(); |
| 5451 | } | 5374 | } |
| ... | @@ -5494,103 +5417,13 @@ fn containerDecl( | ... | @@ -5494,103 +5417,13 @@ fn containerDecl( |
| 5494 | if (container_decl.layout_token) |t| { | 5417 | if (container_decl.layout_token) |t| { |
| 5495 | return astgen.failTok(t, "enums do not support 'packed' or 'extern'; instead provide an explicit integer tag type", .{}); | 5418 | return astgen.failTok(t, "enums do not support 'packed' or 'extern'; instead provide an explicit integer tag type", .{}); |
| 5496 | } | 5419 | } |
| 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 | } | | |
| 5533 | | 5420 | |
| 5534 | const name_token = member.ast.main_token; | 5421 | astgen.advanceSourceCursorToNode(node); |
| 5535 | if (mem.eql(u8, tree.tokenSlice(name_token), "_")) { | 5422 | |
| 5536 | if (opt_nonexhaustive_node.unwrap()) |nonexhaustive_node| { | 5423 | const tag_type_ref: Zir.Inst.Ref = ref: { |
| 5537 | return astgen.failNodeNotes( | 5424 | const arg_node = container_decl.ast.arg.unwrap() orelse break :ref .none; |
| 5538 | member_node, | 5425 | break :ref try typeExpr(gz, scope, arg_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 | }; | | |
| 5575 | }; | 5426 | }; |
| 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; | | |
| 5594 | | 5427 | |
| 5595 | const decl_inst = try gz.reserveInstructionIndex(); | 5428 | const decl_inst = try gz.reserveInstructionIndex(); |
| 5596 | | 5429 | |
| ... | @@ -5605,7 +5438,6 @@ fn containerDecl( | ... | @@ -5605,7 +5438,6 @@ fn containerDecl( |
| 5605 | | 5438 | |
| 5606 | // The enum_decl instruction introduces a scope in which the decls of the enum | 5439 | // The enum_decl instruction introduces a scope in which the decls of the enum |
| 5607 | // are in scope, so that tag values can refer to decls within the enum itself. | 5440 | // are in scope, so that tag values can refer to decls within the enum itself. |
| 5608 | astgen.advanceSourceCursorToNode(node); | | |
| 5609 | var block_scope: GenZir = .{ | 5441 | var block_scope: GenZir = .{ |
| 5610 | .parent = &namespace.base, | 5442 | .parent = &namespace.base, |
| 5611 | .decl_node_index = node, | 5443 | .decl_node_index = node, |
| ... | @@ -5617,104 +5449,111 @@ fn containerDecl( | ... | @@ -5617,104 +5449,111 @@ fn containerDecl( |
| 5617 | }; | 5449 | }; |
| 5618 | defer block_scope.unstack(); | 5450 | defer block_scope.unstack(); |
| 5619 | | 5451 | |
| 5620 | _ = try astgen.scanContainer(&namespace, container_decl.ast.members, .@"enum"); | 5452 | const scan_result = try astgen.scanContainer(&namespace, container_decl.ast.members, .@"enum"); |
| 5621 | namespace.base.tag = .namespace; | 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); |
| 5622 | | 5455 | |
| 5623 | const arg_inst: Zir.Inst.Ref = if (container_decl.ast.arg.unwrap()) |arg| | 5456 | var scratch: Scratch = .init(astgen); |
| 5624 | try comptimeExpr(&block_scope, &namespace.base, coerced_type_ri, arg, .type) | 5457 | defer scratch.reset(); |
| 5625 | else | | |
| 5626 | .none; | | |
| 5627 | | 5458 | |
| 5628 | const bits_per_field = 1; | 5459 | // Replicate the structure of the ZIR trailing data in `scratch` |
| 5629 | const max_field_size = 2; | 5460 | var wip_decls: WipDecls = try .init(&scratch, scan_result.decls_len); |
| 5630 | var wip_members = try WipMembers.init(gpa, &astgen.scratch, @intCast(counts.decls), @intCast(counts.total_fields), bits_per_field, max_field_size); | 5461 | const field_names = try scratch.addSlice(fields_len); |
| 5631 | defer wip_members.deinit(); | 5462 | const field_value_body_lens = try scratch.addOptionalSlice(scan_result.any_field_values, fields_len); |
| 5632 | | 5463 | |
| 5633 | const old_hasher = astgen.src_hasher; | 5464 | const old_hasher = astgen.src_hasher; |
| 5634 | defer astgen.src_hasher = old_hasher; | 5465 | defer astgen.src_hasher = old_hasher; |
| 5635 | astgen.src_hasher = std.zig.SrcHasher.init(.{}); | 5466 | astgen.src_hasher = .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)}); | | |
| 5640 | | 5467 | |
| | 5468 | var next_field_idx: u32 = 0; |
| | 5469 | var opt_nonexhaustive_node: Ast.Node.OptionalIndex = .none; |
| 5641 | for (container_decl.ast.members) |member_node| { | 5470 | for (container_decl.ast.members) |member_node| { |
| 5642 | if (member_node.toOptional() == counts.nonexhaustive_node) | 5471 | var member = switch (try containerMember(&block_scope, &namespace.base, &wip_decls, member_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)) { | | |
| 5646 | .decl => continue, | 5472 | .decl => continue, |
| 5647 | .field => |field| field, | 5473 | .field => |field| field, |
| 5648 | }; | 5474 | }; |
| 5649 | member.convertToNonTupleLike(astgen.tree); | 5475 | member.convertToNonTupleLike(astgen.tree); |
| 5650 | assert(member.comptime_token == null); | 5476 | if (member.ast.tuple_like) return astgen.failTok(member.ast.main_token, "enum field missing name", .{}); |
| 5651 | assert(member.ast.type_expr == .none); | 5477 | if (member.comptime_token) |t| return astgen.failTok(t, "enum fields cannot be marked comptime", .{}); |
| 5652 | assert(member.ast.align_expr == .none); | 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 | } |
| 5653 | | 5501 | |
| 5654 | const field_name = try astgen.identAsString(member.ast.main_token); | 5502 | // This is a real field rather than a non-exhaustive mark. |
| 5655 | wip_members.appendToField(@intFromEnum(field_name)); | 5503 | const field_idx = next_field_idx; |
| | 5504 | next_field_idx += 1; |
| 5656 | | 5505 | |
| 5657 | const have_value = member.ast.value_expr != .none; | 5506 | astgen.src_hasher.update(tree.getNodeSource(member_node)); |
| 5658 | wip_members.nextField(bits_per_field, .{have_value}); | | |
| 5659 | | 5507 | |
| 5660 | if (member.ast.value_expr.unwrap()) |value_expr| { | 5508 | field_names.get(astgen)[field_idx] = @intFromEnum(try astgen.identAsString(member.ast.main_token)); |
| 5661 | if (arg_inst == .none) { | 5509 | |
| 5662 | return astgen.failNodeNotes( | 5510 | if (member.ast.value_expr.unwrap()) |value_node| { |
| 5663 | node, | 5511 | if (tag_type_ref == .none) { |
| 5664 | "explicitly valued enum missing integer tag type", | 5512 | return astgen.failNodeNotes(node, "explicitly valued enum missing integer tag type", .{}, &.{ |
| 5665 | .{}, | 5513 | try astgen.errNoteNode(value_node, "tag value specified here", .{}), |
| 5666 | &[_]u32{ | 5514 | }); |
| 5667 | try astgen.errNoteNode( | 5515 | } |
| 5668 | value_expr, | 5516 | const val_ri: ResultInfo = .{ .rl = .{ .coerced_ty = decl_inst.toRef() } }; |
| 5669 | "tag value specified here", | 5517 | const value_ref = try expr(&block_scope, &namespace.base, val_ri, value_node); |
| 5670 | .{}, | 5518 | if (!block_scope.endsWithNoReturn()) { |
| 5671 | ), | 5519 | _ = try block_scope.addBreak(.break_inline, decl_inst, value_ref); |
| 5672 | }, | | |
| 5673 | ); | | |
| 5674 | } | 5520 | } |
| 5675 | const tag_value_inst = try expr(&block_scope, &namespace.base, .{ .rl = .{ .ty = arg_inst } }, value_expr); | 5521 | const body_len = try scratch.appendBodyWithFixups(block_scope.instructionsSlice()); |
| 5676 | wip_members.appendToField(@intFromEnum(tag_value_inst)); | 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; |
| 5677 | } | 5526 | } |
| 5678 | } | 5527 | } |
| 5679 | | 5528 | assert(scan_result.has_underscore_field == (opt_nonexhaustive_node != .none)); |
| 5680 | if (!block_scope.isEmpty()) { | 5529 | assert(next_field_idx == fields_len); |
| 5681 | _ = try block_scope.addBreak(.break_inline, decl_inst, .void_value); | 5530 | wip_decls.finish(); |
| 5682 | } | | |
| 5683 | | 5531 | |
| 5684 | var fields_hash: std.zig.SrcHash = undefined; | 5532 | var fields_hash: std.zig.SrcHash = undefined; |
| 5685 | astgen.src_hasher.final(&fields_hash); | 5533 | astgen.src_hasher.final(&fields_hash); |
| 5686 | | 5534 | |
| 5687 | const body = block_scope.instructionsSlice(); | | |
| 5688 | const body_len = astgen.countBodyLenAfterFixups(body); | | |
| 5689 | | | |
| 5690 | try gz.setEnum(decl_inst, .{ | 5535 | try gz.setEnum(decl_inst, .{ |
| 5691 | .src_node = node, | 5536 | .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, | | |
| 5699 | .name_strat = name_strat, | 5537 | .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), |
| 5700 | }); | 5547 | }); |
| 5701 | | 5548 | |
| 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 | | | |
| 5712 | block_scope.unstack(); | 5549 | block_scope.unstack(); |
| 5713 | return rvalue(gz, ri, decl_inst.toRef(), node); | 5550 | return rvalue(gz, ri, decl_inst.toRef(), node); |
| 5714 | }, | 5551 | }, |
| 5715 | .keyword_opaque => { | 5552 | .keyword_opaque => { |
| 5716 | assert(container_decl.ast.arg == .none); | 5553 | assert(container_decl.ast.arg == .none); |
| 5717 | | 5554 | |
| | 5555 | astgen.advanceSourceCursorToNode(node); |
| | 5556 | |
| 5718 | const decl_inst = try gz.reserveInstructionIndex(); | 5557 | const decl_inst = try gz.reserveInstructionIndex(); |
| 5719 | | 5558 | |
| 5720 | var namespace: Scope.Namespace = .{ | 5559 | var namespace: Scope.Namespace = .{ |
| ... | @@ -5726,7 +5565,6 @@ fn containerDecl( | ... | @@ -5726,7 +5565,6 @@ fn containerDecl( |
| 5726 | }; | 5565 | }; |
| 5727 | defer namespace.deinit(gpa); | 5566 | defer namespace.deinit(gpa); |
| 5728 | | 5567 | |
| 5729 | astgen.advanceSourceCursorToNode(node); | | |
| 5730 | var block_scope: GenZir = .{ | 5568 | var block_scope: GenZir = .{ |
| 5731 | .parent = &namespace.base, | 5569 | .parent = &namespace.base, |
| 5732 | .decl_node_index = node, | 5570 | .decl_node_index = node, |
| ... | @@ -5738,36 +5576,34 @@ fn containerDecl( | ... | @@ -5738,36 +5576,34 @@ fn containerDecl( |
| 5738 | }; | 5576 | }; |
| 5739 | defer block_scope.unstack(); | 5577 | defer block_scope.unstack(); |
| 5740 | | 5578 | |
| 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"); |
| 5742 | | 5580 | |
| 5743 | var wip_members = try WipMembers.init(gpa, &astgen.scratch, decl_count, 0, 0, 0); | 5581 | var scratch: Scratch = .init(astgen); |
| 5744 | defer wip_members.deinit(); | 5582 | defer scratch.reset(); |
| | 5583 | var wip_decls: WipDecls = try .init(&scratch, scan_result.decls_len); |
| 5745 | | 5584 | |
| 5746 | if (container_decl.layout_token) |layout_token| { | 5585 | if (container_decl.layout_token) |layout_token| { |
| 5747 | return astgen.failTok(layout_token, "opaque types do not support 'packed' or 'extern'", .{}); | 5586 | return astgen.failTok(layout_token, "opaque types do not support 'packed' or 'extern'", .{}); |
| 5748 | } | 5587 | } |
| 5749 | | 5588 | |
| 5750 | for (container_decl.ast.members) |member_node| { | 5589 | for (container_decl.ast.members) |member_node| { |
| 5751 | const res = try containerMember(&block_scope, &namespace.base, &wip_members, member_node); | 5590 | switch (try containerMember(&block_scope, &namespace.base, &wip_decls, member_node)) { |
| 5752 | if (res == .field) { | 5591 | .decl => {}, |
| 5753 | return astgen.failNode(member_node, "opaque types cannot have fields", .{}); | 5592 | .field => return astgen.failNode(member_node, "opaque types cannot have fields", .{}), |
| 5754 | } | 5593 | } |
| 5755 | } | 5594 | } |
| 5756 | | 5595 | |
| | 5596 | wip_decls.finish(); |
| | 5597 | |
| 5757 | try gz.setOpaque(decl_inst, .{ | 5598 | try gz.setOpaque(decl_inst, .{ |
| 5758 | .src_node = node, | 5599 | .src_node = node, |
| 5759 | .captures_len = @intCast(namespace.captures.count()), | | |
| 5760 | .decls_len = decl_count, | | |
| 5761 | .name_strat = name_strat, | 5600 | .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)), |
| 5762 | }); | 5605 | }); |
| 5763 | | 5606 | |
| 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 | | | |
| 5771 | block_scope.unstack(); | 5607 | block_scope.unstack(); |
| 5772 | return rvalue(gz, ri, decl_inst.toRef(), node); | 5608 | return rvalue(gz, ri, decl_inst.toRef(), node); |
| 5773 | }, | 5609 | }, |
| ... | @@ -5780,7 +5616,7 @@ const ContainerMemberResult = union(enum) { decl, field: Ast.full.ContainerField | ... | @@ -5780,7 +5616,7 @@ const ContainerMemberResult = union(enum) { decl, field: Ast.full.ContainerField |
| 5780 | fn containerMember( | 5616 | fn containerMember( |
| 5781 | gz: *GenZir, | 5617 | gz: *GenZir, |
| 5782 | scope: *Scope, | 5618 | scope: *Scope, |
| 5783 | wip_members: *WipMembers, | 5619 | wip_decls: *WipDecls, |
| 5784 | member_node: Ast.Node.Index, | 5620 | member_node: Ast.Node.Index, |
| 5785 | ) InnerError!ContainerMemberResult { | 5621 | ) InnerError!ContainerMemberResult { |
| 5786 | const astgen = gz.astgen; | 5622 | const astgen = gz.astgen; |
| ... | @@ -5805,13 +5641,13 @@ fn containerMember( | ... | @@ -5805,13 +5641,13 @@ fn containerMember( |
| 5805 | else | 5641 | else |
| 5806 | .none; | 5642 | .none; |
| 5807 | | 5643 | |
| 5808 | const prev_decl_index = wip_members.decl_index; | 5644 | const prev_decl_index = wip_decls.index; |
| 5809 | astgen.fnDecl(gz, scope, wip_members, member_node, body, full) catch |err| switch (err) { | 5645 | astgen.fnDecl(gz, scope, wip_decls, member_node, body, full) catch |err| switch (err) { |
| 5810 | error.OutOfMemory => return error.OutOfMemory, | 5646 | error.OutOfMemory => return error.OutOfMemory, |
| 5811 | error.AnalysisFail => { | 5647 | error.AnalysisFail => { |
| 5812 | wip_members.decl_index = prev_decl_index; | 5648 | wip_decls.index = prev_decl_index; |
| 5813 | try addFailedDeclaration( | 5649 | try addFailedDeclaration( |
| 5814 | wip_members, | 5650 | wip_decls, |
| 5815 | gz, | 5651 | gz, |
| 5816 | .@"const", | 5652 | .@"const", |
| 5817 | try astgen.identAsString(full.name_token.?), | 5653 | try astgen.identAsString(full.name_token.?), |
| ... | @@ -5828,13 +5664,13 @@ fn containerMember( | ... | @@ -5828,13 +5664,13 @@ fn containerMember( |
| 5828 | .aligned_var_decl, | 5664 | .aligned_var_decl, |
| 5829 | => { | 5665 | => { |
| 5830 | const full = tree.fullVarDecl(member_node).?; | 5666 | const full = tree.fullVarDecl(member_node).?; |
| 5831 | const prev_decl_index = wip_members.decl_index; | 5667 | const prev_decl_index = wip_decls.index; |
| 5832 | astgen.globalVarDecl(gz, scope, wip_members, member_node, full) catch |err| switch (err) { | 5668 | astgen.globalVarDecl(gz, scope, wip_decls, member_node, full) catch |err| switch (err) { |
| 5833 | error.OutOfMemory => return error.OutOfMemory, | 5669 | error.OutOfMemory => return error.OutOfMemory, |
| 5834 | error.AnalysisFail => { | 5670 | error.AnalysisFail => { |
| 5835 | wip_members.decl_index = prev_decl_index; | 5671 | wip_decls.index = prev_decl_index; |
| 5836 | try addFailedDeclaration( | 5672 | try addFailedDeclaration( |
| 5837 | wip_members, | 5673 | wip_decls, |
| 5838 | gz, | 5674 | gz, |
| 5839 | .@"const", // doesn't really matter | 5675 | .@"const", // doesn't really matter |
| 5840 | try astgen.identAsString(full.ast.mut_token + 1), | 5676 | try astgen.identAsString(full.ast.mut_token + 1), |
| ... | @@ -5846,13 +5682,13 @@ fn containerMember( | ... | @@ -5846,13 +5682,13 @@ fn containerMember( |
| 5846 | }, | 5682 | }, |
| 5847 | | 5683 | |
| 5848 | .@"comptime" => { | 5684 | .@"comptime" => { |
| 5849 | const prev_decl_index = wip_members.decl_index; | 5685 | const prev_decl_index = wip_decls.index; |
| 5850 | astgen.comptimeDecl(gz, scope, wip_members, member_node) catch |err| switch (err) { | 5686 | astgen.comptimeDecl(gz, scope, wip_decls, member_node) catch |err| switch (err) { |
| 5851 | error.OutOfMemory => return error.OutOfMemory, | 5687 | error.OutOfMemory => return error.OutOfMemory, |
| 5852 | error.AnalysisFail => { | 5688 | error.AnalysisFail => { |
| 5853 | wip_members.decl_index = prev_decl_index; | 5689 | wip_decls.index = prev_decl_index; |
| 5854 | try addFailedDeclaration( | 5690 | try addFailedDeclaration( |
| 5855 | wip_members, | 5691 | wip_decls, |
| 5856 | gz, | 5692 | gz, |
| 5857 | .@"comptime", | 5693 | .@"comptime", |
| 5858 | .empty, | 5694 | .empty, |
| ... | @@ -5863,16 +5699,16 @@ fn containerMember( | ... | @@ -5863,16 +5699,16 @@ fn containerMember( |
| 5863 | }; | 5699 | }; |
| 5864 | }, | 5700 | }, |
| 5865 | .test_decl => { | 5701 | .test_decl => { |
| 5866 | const prev_decl_index = wip_members.decl_index; | 5702 | const prev_decl_index = wip_decls.index; |
| 5867 | // We need to have *some* decl here so that the decl count matches what's expected. | 5703 | // We need to have *some* decl here so that the decl count matches what's expected. |
| 5868 | // Since it doesn't strictly matter *what* this is, let's save ourselves the trouble | 5704 | // Since it doesn't strictly matter *what* this is, let's save ourselves the trouble |
| 5869 | // of duplicating the test name logic, and just assume this is an unnamed test. | 5705 | // 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) { |
| 5871 | error.OutOfMemory => return error.OutOfMemory, | 5707 | error.OutOfMemory => return error.OutOfMemory, |
| 5872 | error.AnalysisFail => { | 5708 | error.AnalysisFail => { |
| 5873 | wip_members.decl_index = prev_decl_index; | 5709 | wip_decls.index = prev_decl_index; |
| 5874 | try addFailedDeclaration( | 5710 | try addFailedDeclaration( |
| 5875 | wip_members, | 5711 | wip_decls, |
| 5876 | gz, | 5712 | gz, |
| 5877 | .unnamed_test, | 5713 | .unnamed_test, |
| 5878 | .empty, | 5714 | .empty, |
| ... | @@ -10619,495 +10455,19 @@ fn nodeMayEvalToError(tree: *const Ast, start_node: Ast.Node.Index) BuiltinFn.Ev | ... | @@ -10619,495 +10455,19 @@ fn nodeMayEvalToError(tree: *const Ast, start_node: Ast.Node.Index) BuiltinFn.Ev |
| 10619 | } | 10455 | } |
| 10620 | } | 10456 | } |
| 10621 | | 10457 | |
| 10622 | /// Returns `true` if it is known the type expression has more than one possible value; | 10458 | /// Applies `rl` semantics to `result`. Expressions which do not do their own handling of |
| 10623 | /// `false` otherwise. | 10459 | /// result locations must call this function on their result. |
| 10624 | fn nodeImpliesMoreThanOnePossibleValue(tree: *const Ast, start_node: Ast.Node.Index) bool { | 10460 | /// As an example, if `ri.rl` is `.ptr`, it will write the result to the pointer. |
| 10625 | var node = start_node; | 10461 | /// If `ri.rl` is `.ty`, it will coerce the result to the type. |
| 10626 | while (true) { | 10462 | /// Assumes nothing stacked on `gz`. |
| 10627 | switch (tree.nodeTag(node)) { | 10463 | fn rvalue( |
| 10628 | .root, | 10464 | gz: *GenZir, |
| 10629 | .test_decl, | 10465 | ri: ResultInfo, |
| 10630 | .switch_case, | 10466 | raw_result: Zir.Inst.Ref, |
| 10631 | .switch_case_inline, | 10467 | src_node: Ast.Node.Index, |
| 10632 | .switch_case_one, | 10468 | ) InnerError!Zir.Inst.Ref { |
| 10633 | .switch_case_inline_one, | 10469 | return rvalueInner(gz, ri, raw_result, src_node, true); |
| 10634 | .container_field_init, | 10470 | } |
| 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. | | |
| 10862 | fn 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`. | | |
| 11103 | fn 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 | } | | |
| 11111 | | 10471 | |
| 11112 | /// Like `rvalue`, but refuses to perform coercions before taking references for | 10472 | /// Like `rvalue`, but refuses to perform coercions before taking references for |
| 11113 | /// the `ref_coerced_ty` result type. This is used for local variables which do | 10473 | /// the `ref_coerced_ty` result type. This is used for local variables which do |
| ... | @@ -13044,18 +12404,19 @@ const GenZir = struct { | ... | @@ -13044,18 +12404,19 @@ const GenZir = struct { |
| 13044 | | 12404 | |
| 13045 | fn setStruct(gz: *GenZir, inst: Zir.Inst.Index, args: struct { | 12405 | fn setStruct(gz: *GenZir, inst: Zir.Inst.Index, args: struct { |
| 13046 | src_node: Ast.Node.Index, | 12406 | src_node: Ast.Node.Index, |
| 13047 | captures_len: u32, | 12407 | name_strat: Zir.Inst.NameStrategy, |
| 13048 | fields_len: u32, | | |
| 13049 | decls_len: u32, | | |
| 13050 | has_backing_int: bool, | | |
| 13051 | layout: std.builtin.Type.ContainerLayout, | 12408 | layout: std.builtin.Type.ContainerLayout, |
| 13052 | known_non_opv: bool, | 12409 | backing_int_type: Zir.Inst.Ref, |
| 13053 | known_comptime_only: bool, | 12410 | decls_len: u32, |
| | 12411 | fields_len: u32, |
| | 12412 | any_field_aligns: bool, |
| | 12413 | any_field_defaults: bool, |
| 13054 | any_comptime_fields: bool, | 12414 | any_comptime_fields: bool, |
| 13055 | any_default_inits: bool, | | |
| 13056 | any_aligned_fields: bool, | | |
| 13057 | fields_hash: std.zig.SrcHash, | 12415 | 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, |
| 13059 | }) !void { | 12420 | }) !void { |
| 13060 | const astgen = gz.astgen; | 12421 | const astgen = gz.astgen; |
| 13061 | const gpa = astgen.gpa; | 12422 | const gpa = astgen.gpa; |
| ... | @@ -13063,9 +12424,16 @@ const GenZir = struct { | ... | @@ -13063,9 +12424,16 @@ const GenZir = struct { |
| 13063 | // Node .root is valid for the root `struct_decl` of a file! | 12424 | // Node .root is valid for the root `struct_decl` of a file! |
| 13064 | assert(args.src_node != .root or gz.parent.tag == .top); | 12425 | assert(args.src_node != .root or gz.parent.tag == .top); |
| 13065 | | 12426 | |
| | 12427 | const captures_len: u32 = @intCast(args.captures.len); |
| | 12428 | assert(args.capture_names.len == captures_len); |
| | 12429 | |
| 13066 | const fields_hash_arr: [4]u32 = @bitCast(args.fields_hash); | 12430 | const fields_hash_arr: [4]u32 = @bitCast(args.fields_hash); |
| 13067 | | 12431 | |
| 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 | |
| 13069 | const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.StructDecl{ | 12437 | const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.StructDecl{ |
| 13070 | .fields_hash_0 = fields_hash_arr[0], | 12438 | .fields_hash_0 = fields_hash_arr[0], |
| 13071 | .fields_hash_1 = fields_hash_arr[1], | 12439 | .fields_hash_1 = fields_hash_arr[1], |
| ... | @@ -13075,31 +12443,28 @@ const GenZir = struct { | ... | @@ -13075,31 +12443,28 @@ const GenZir = struct { |
| 13075 | .src_node = args.src_node, | 12443 | .src_node = args.src_node, |
| 13076 | }); | 12444 | }); |
| 13077 | | 12445 | |
| 13078 | if (args.captures_len != 0) { | 12446 | if (captures_len != 0) astgen.extra.appendAssumeCapacity(captures_len); |
| 13079 | astgen.extra.appendAssumeCapacity(args.captures_len); | 12447 | if (args.decls_len != 0) astgen.extra.appendAssumeCapacity(args.decls_len); |
| 13080 | } | 12448 | if (args.fields_len != 0) astgen.extra.appendAssumeCapacity(args.fields_len); |
| 13081 | if (args.fields_len != 0) { | 12449 | if (args.backing_int_type != .none) astgen.extra.appendAssumeCapacity(@intFromEnum(args.backing_int_type)); |
| 13082 | astgen.extra.appendAssumeCapacity(args.fields_len); | 12450 | astgen.extra.appendSliceAssumeCapacity(@ptrCast(args.captures)); |
| 13083 | } | 12451 | astgen.extra.appendSliceAssumeCapacity(@ptrCast(args.capture_names)); |
| 13084 | if (args.decls_len != 0) { | 12452 | astgen.extra.appendSliceAssumeCapacity(args.remaining); |
| 13085 | astgen.extra.appendAssumeCapacity(args.decls_len); | 12453 | |
| 13086 | } | | |
| 13087 | astgen.instructions.set(@intFromEnum(inst), .{ | 12454 | astgen.instructions.set(@intFromEnum(inst), .{ |
| 13088 | .tag = .extended, | 12455 | .tag = .extended, |
| 13089 | .data = .{ .extended = .{ | 12456 | .data = .{ .extended = .{ |
| 13090 | .opcode = .struct_decl, | 12457 | .opcode = .struct_decl, |
| 13091 | .small = @bitCast(Zir.Inst.StructDecl.Small{ | 12458 | .small = @bitCast(Zir.Inst.StructDecl.Small{ |
| 13092 | .has_captures_len = args.captures_len != 0, | 12459 | .has_captures_len = captures_len != 0, |
| 13093 | .has_fields_len = args.fields_len != 0, | | |
| 13094 | .has_decls_len = args.decls_len != 0, | 12460 | .has_decls_len = args.decls_len != 0, |
| 13095 | .has_backing_int = args.has_backing_int, | 12461 | .has_fields_len = args.fields_len != 0, |
| 13096 | .known_non_opv = args.known_non_opv, | | |
| 13097 | .known_comptime_only = args.known_comptime_only, | | |
| 13098 | .name_strategy = args.name_strat, | 12462 | .name_strategy = args.name_strat, |
| 13099 | .layout = args.layout, | 12463 | .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, |
| 13100 | .any_comptime_fields = args.any_comptime_fields, | 12467 | .any_comptime_fields = args.any_comptime_fields, |
| 13101 | .any_default_inits = args.any_default_inits, | | |
| 13102 | .any_aligned_fields = args.any_aligned_fields, | | |
| 13103 | }), | 12468 | }), |
| 13104 | .operand = payload_index, | 12469 | .operand = payload_index, |
| 13105 | } }, | 12470 | } }, |
| ... | @@ -13108,25 +12473,34 @@ const GenZir = struct { | ... | @@ -13108,25 +12473,34 @@ const GenZir = struct { |
| 13108 | | 12473 | |
| 13109 | fn setUnion(gz: *GenZir, inst: Zir.Inst.Index, args: struct { | 12474 | fn setUnion(gz: *GenZir, inst: Zir.Inst.Index, args: struct { |
| 13110 | src_node: Ast.Node.Index, | 12475 | src_node: Ast.Node.Index, |
| 13111 | tag_type: Zir.Inst.Ref, | 12476 | name_strat: Zir.Inst.NameStrategy, |
| 13112 | captures_len: u32, | 12477 | kind: Zir.Inst.UnionDecl.Kind, |
| 13113 | body_len: u32, | 12478 | arg_type: Zir.Inst.Ref, |
| 13114 | fields_len: u32, | | |
| 13115 | decls_len: u32, | 12479 | decls_len: u32, |
| 13116 | layout: std.builtin.Type.ContainerLayout, | 12480 | fields_len: u32, |
| 13117 | auto_enum_tag: bool, | 12481 | any_field_aligns: bool, |
| 13118 | any_aligned_fields: bool, | 12482 | any_field_values: bool, |
| 13119 | fields_hash: std.zig.SrcHash, | 12483 | 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, |
| 13121 | }) !void { | 12488 | }) !void { |
| 13122 | const astgen = gz.astgen; | 12489 | const astgen = gz.astgen; |
| 13123 | const gpa = astgen.gpa; | 12490 | const gpa = astgen.gpa; |
| 13124 | | 12491 | |
| 13125 | assert(args.src_node != .root); | 12492 | assert(args.src_node != .root); |
| 13126 | | 12493 | |
| | 12494 | const captures_len: u32 = @intCast(args.captures.len); |
| | 12495 | assert(args.capture_names.len == captures_len); |
| | 12496 | |
| 13127 | const fields_hash_arr: [4]u32 = @bitCast(args.fields_hash); | 12497 | const fields_hash_arr: [4]u32 = @bitCast(args.fields_hash); |
| 13128 | | 12498 | |
| 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 | |
| 13130 | const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.UnionDecl{ | 12504 | const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.UnionDecl{ |
| 13131 | .fields_hash_0 = fields_hash_arr[0], | 12505 | .fields_hash_0 = fields_hash_arr[0], |
| 13132 | .fields_hash_1 = fields_hash_arr[1], | 12506 | .fields_hash_1 = fields_hash_arr[1], |
| ... | @@ -13136,60 +12510,68 @@ const GenZir = struct { | ... | @@ -13136,60 +12510,68 @@ const GenZir = struct { |
| 13136 | .src_node = args.src_node, | 12510 | .src_node = args.src_node, |
| 13137 | }); | 12511 | }); |
| 13138 | | 12512 | |
| 13139 | if (args.tag_type != .none) { | 12513 | if (captures_len != 0) astgen.extra.appendAssumeCapacity(captures_len); |
| 13140 | astgen.extra.appendAssumeCapacity(@intFromEnum(args.tag_type)); | 12514 | if (args.decls_len != 0) astgen.extra.appendAssumeCapacity(args.decls_len); |
| 13141 | } | 12515 | if (args.fields_len != 0) astgen.extra.appendAssumeCapacity(args.fields_len); |
| 13142 | if (args.captures_len != 0) { | 12516 | if (args.kind.hasArgType()) { |
| 13143 | astgen.extra.appendAssumeCapacity(args.captures_len); | 12517 | assert(args.arg_type != .none); |
| 13144 | } | 12518 | astgen.extra.appendAssumeCapacity(@intFromEnum(args.arg_type)); |
| 13145 | if (args.body_len != 0) { | 12519 | } else { |
| 13146 | astgen.extra.appendAssumeCapacity(args.body_len); | 12520 | assert(args.arg_type == .none); |
| 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); | | |
| 13153 | } | 12521 | } |
| | 12522 | astgen.extra.appendSliceAssumeCapacity(@ptrCast(args.captures)); |
| | 12523 | astgen.extra.appendSliceAssumeCapacity(@ptrCast(args.capture_names)); |
| | 12524 | astgen.extra.appendSliceAssumeCapacity(args.remaining); |
| | 12525 | |
| 13154 | astgen.instructions.set(@intFromEnum(inst), .{ | 12526 | astgen.instructions.set(@intFromEnum(inst), .{ |
| 13155 | .tag = .extended, | 12527 | .tag = .extended, |
| 13156 | .data = .{ .extended = .{ | 12528 | .data = .{ |
| 13157 | .opcode = .union_decl, | 12529 | .extended = .{ |
| 13158 | .small = @bitCast(Zir.Inst.UnionDecl.Small{ | 12530 | .opcode = .union_decl, |
| 13159 | .has_tag_type = args.tag_type != .none, | 12531 | .small = @bitCast(Zir.Inst.UnionDecl.Small{ |
| 13160 | .has_captures_len = args.captures_len != 0, | 12532 | .has_captures_len = captures_len != 0, |
| 13161 | .has_body_len = args.body_len != 0, | 12533 | .has_decls_len = args.decls_len != 0, |
| 13162 | .has_fields_len = args.fields_len != 0, | 12534 | .has_fields_len = args.fields_len != 0, |
| 13163 | .has_decls_len = args.decls_len != 0, | 12535 | .name_strategy = args.name_strat, |
| 13164 | .name_strategy = args.name_strat, | 12536 | .kind = args.kind, |
| 13165 | .layout = args.layout, | 12537 | .any_field_aligns = args.any_field_aligns, |
| 13166 | .auto_enum_tag = args.auto_enum_tag, | 12538 | .any_field_values = args.any_field_values, |
| 13167 | .any_aligned_fields = args.any_aligned_fields, | 12539 | }), |
| 13168 | }), | 12540 | .operand = payload_index, |
| 13169 | .operand = payload_index, | 12541 | }, |
| 13170 | } }, | 12542 | }, |
| 13171 | }); | 12543 | }); |
| 13172 | } | 12544 | } |
| 13173 | | 12545 | |
| 13174 | fn setEnum(gz: *GenZir, inst: Zir.Inst.Index, args: struct { | 12546 | fn setEnum(gz: *GenZir, inst: Zir.Inst.Index, args: struct { |
| 13175 | src_node: Ast.Node.Index, | 12547 | src_node: Ast.Node.Index, |
| | 12548 | name_strat: Zir.Inst.NameStrategy, |
| 13176 | tag_type: Zir.Inst.Ref, | 12549 | tag_type: Zir.Inst.Ref, |
| 13177 | captures_len: u32, | | |
| 13178 | body_len: u32, | | |
| 13179 | fields_len: u32, | | |
| 13180 | decls_len: u32, | | |
| 13181 | nonexhaustive: bool, | 12550 | nonexhaustive: bool, |
| | 12551 | decls_len: u32, |
| | 12552 | fields_len: u32, |
| | 12553 | any_field_values: bool, |
| 13182 | fields_hash: std.zig.SrcHash, | 12554 | 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, |
| 13184 | }) !void { | 12559 | }) !void { |
| 13185 | const astgen = gz.astgen; | 12560 | const astgen = gz.astgen; |
| 13186 | const gpa = astgen.gpa; | 12561 | const gpa = astgen.gpa; |
| 13187 | | 12562 | |
| 13188 | assert(args.src_node != .root); | 12563 | assert(args.src_node != .root); |
| 13189 | | 12564 | |
| | 12565 | const captures_len: u32 = @intCast(args.captures.len); |
| | 12566 | assert(args.capture_names.len == captures_len); |
| | 12567 | |
| 13190 | const fields_hash_arr: [4]u32 = @bitCast(args.fields_hash); | 12568 | const fields_hash_arr: [4]u32 = @bitCast(args.fields_hash); |
| 13191 | | 12569 | |
| 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 | |
| 13193 | const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.EnumDecl{ | 12575 | const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.EnumDecl{ |
| 13194 | .fields_hash_0 = fields_hash_arr[0], | 12576 | .fields_hash_0 = fields_hash_arr[0], |
| 13195 | .fields_hash_1 = fields_hash_arr[1], | 12577 | .fields_hash_1 = fields_hash_arr[1], |
| ... | @@ -13199,33 +12581,26 @@ const GenZir = struct { | ... | @@ -13199,33 +12581,26 @@ const GenZir = struct { |
| 13199 | .src_node = args.src_node, | 12581 | .src_node = args.src_node, |
| 13200 | }); | 12582 | }); |
| 13201 | | 12583 | |
| 13202 | if (args.tag_type != .none) { | 12584 | if (captures_len != 0) astgen.extra.appendAssumeCapacity(captures_len); |
| 13203 | astgen.extra.appendAssumeCapacity(@intFromEnum(args.tag_type)); | 12585 | if (args.decls_len != 0) astgen.extra.appendAssumeCapacity(args.decls_len); |
| 13204 | } | 12586 | if (args.fields_len != 0) astgen.extra.appendAssumeCapacity(args.fields_len); |
| 13205 | if (args.captures_len != 0) { | 12587 | if (args.tag_type != .none) astgen.extra.appendAssumeCapacity(@intFromEnum(args.tag_type)); |
| 13206 | astgen.extra.appendAssumeCapacity(args.captures_len); | 12588 | astgen.extra.appendSliceAssumeCapacity(@ptrCast(args.captures)); |
| 13207 | } | 12589 | astgen.extra.appendSliceAssumeCapacity(@ptrCast(args.capture_names)); |
| 13208 | if (args.body_len != 0) { | 12590 | astgen.extra.appendSliceAssumeCapacity(args.remaining); |
| 13209 | astgen.extra.appendAssumeCapacity(args.body_len); | 12591 | |
| 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 | } | | |
| 13217 | astgen.instructions.set(@intFromEnum(inst), .{ | 12592 | astgen.instructions.set(@intFromEnum(inst), .{ |
| 13218 | .tag = .extended, | 12593 | .tag = .extended, |
| 13219 | .data = .{ .extended = .{ | 12594 | .data = .{ .extended = .{ |
| 13220 | .opcode = .enum_decl, | 12595 | .opcode = .enum_decl, |
| 13221 | .small = @bitCast(Zir.Inst.EnumDecl.Small{ | 12596 | .small = @bitCast(Zir.Inst.EnumDecl.Small{ |
| 13222 | .has_tag_type = args.tag_type != .none, | 12597 | .has_captures_len = captures_len != 0, |
| 13223 | .has_captures_len = args.captures_len != 0, | | |
| 13224 | .has_body_len = args.body_len != 0, | | |
| 13225 | .has_fields_len = args.fields_len != 0, | | |
| 13226 | .has_decls_len = args.decls_len != 0, | 12598 | .has_decls_len = args.decls_len != 0, |
| | 12599 | .has_fields_len = args.fields_len != 0, |
| 13227 | .name_strategy = args.name_strat, | 12600 | .name_strategy = args.name_strat, |
| | 12601 | .has_tag_type = args.tag_type != .none, |
| 13228 | .nonexhaustive = args.nonexhaustive, | 12602 | .nonexhaustive = args.nonexhaustive, |
| | 12603 | .any_field_values = args.any_field_values, |
| 13229 | }), | 12604 | }), |
| 13230 | .operand = payload_index, | 12605 | .operand = payload_index, |
| 13231 | } }, | 12606 | } }, |
| ... | @@ -13234,33 +12609,41 @@ const GenZir = struct { | ... | @@ -13234,33 +12609,41 @@ const GenZir = struct { |
| 13234 | | 12609 | |
| 13235 | fn setOpaque(gz: *GenZir, inst: Zir.Inst.Index, args: struct { | 12610 | fn setOpaque(gz: *GenZir, inst: Zir.Inst.Index, args: struct { |
| 13236 | src_node: Ast.Node.Index, | 12611 | src_node: Ast.Node.Index, |
| 13237 | captures_len: u32, | | |
| 13238 | decls_len: u32, | | |
| 13239 | name_strat: Zir.Inst.NameStrategy, | 12612 | 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, |
| 13240 | }) !void { | 12617 | }) !void { |
| 13241 | const astgen = gz.astgen; | 12618 | const astgen = gz.astgen; |
| 13242 | const gpa = astgen.gpa; | 12619 | const gpa = astgen.gpa; |
| 13243 | | 12620 | |
| 13244 | assert(args.src_node != .root); | 12621 | assert(args.src_node != .root); |
| 13245 | | 12622 | |
| 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 | |
| 13247 | const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.OpaqueDecl{ | 12631 | const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.OpaqueDecl{ |
| 13248 | .src_line = astgen.source_line, | 12632 | .src_line = astgen.source_line, |
| 13249 | .src_node = args.src_node, | 12633 | .src_node = args.src_node, |
| 13250 | }); | 12634 | }); |
| | 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)); |
| 13251 | | 12640 | |
| 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 | } | | |
| 13258 | astgen.instructions.set(@intFromEnum(inst), .{ | 12641 | astgen.instructions.set(@intFromEnum(inst), .{ |
| 13259 | .tag = .extended, | 12642 | .tag = .extended, |
| 13260 | .data = .{ .extended = .{ | 12643 | .data = .{ .extended = .{ |
| 13261 | .opcode = .opaque_decl, | 12644 | .opcode = .opaque_decl, |
| 13262 | .small = @bitCast(Zir.Inst.OpaqueDecl.Small{ | 12645 | .small = @bitCast(Zir.Inst.OpaqueDecl.Small{ |
| 13263 | .has_captures_len = args.captures_len != 0, | 12646 | .has_captures_len = captures_len != 0, |
| 13264 | .has_decls_len = args.decls_len != 0, | 12647 | .has_decls_len = args.decls_len != 0, |
| 13265 | .name_strategy = args.name_strat, | 12648 | .name_strategy = args.name_strat, |
| 13266 | }), | 12649 | }), |
| ... | @@ -13484,14 +12867,24 @@ fn restoreSourceCursor(astgen: *AstGen, cursor: SourceCursor) void { | ... | @@ -13484,14 +12867,24 @@ fn restoreSourceCursor(astgen: *AstGen, cursor: SourceCursor) void { |
| 13484 | astgen.source_column = cursor.column; | 12867 | astgen.source_column = cursor.column; |
| 13485 | } | 12868 | } |
| 13486 | | 12869 | |
| | 12870 | const 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 | |
| 13487 | /// Detects name conflicts for decls and fields, and populates `namespace.decls` with all named declarations. | 12881 | /// 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). | | |
| 13489 | fn scanContainer( | 12882 | fn scanContainer( |
| 13490 | astgen: *AstGen, | 12883 | astgen: *AstGen, |
| 13491 | namespace: *Scope.Namespace, | 12884 | namespace: *Scope.Namespace, |
| 13492 | members: []const Ast.Node.Index, | 12885 | members: []const Ast.Node.Index, |
| 13493 | container_kind: enum { @"struct", @"union", @"enum", @"opaque" }, | 12886 | container_kind: enum { @"struct", @"union", @"enum", @"opaque" }, |
| 13494 | ) !u32 { | 12887 | ) !ScanContainerResult { |
| 13495 | const gpa = astgen.gpa; | 12888 | const gpa = astgen.gpa; |
| 13496 | const tree = astgen.tree; | 12889 | const tree = astgen.tree; |
| 13497 | | 12890 | |
| ... | @@ -13521,6 +12914,10 @@ fn scanContainer( | ... | @@ -13521,6 +12914,10 @@ fn scanContainer( |
| 13521 | | 12914 | |
| 13522 | var any_duplicates = false; | 12915 | var any_duplicates = false; |
| 13523 | var decl_count: u32 = 0; | 12916 | 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; |
| 13524 | for (members) |member_node| { | 12921 | for (members) |member_node| { |
| 13525 | const Kind = enum { decl, field }; | 12922 | const Kind = enum { decl, field }; |
| 13526 | const kind: Kind, const name_token = switch (tree.nodeTag(member_node)) { | 12923 | const kind: Kind, const name_token = switch (tree.nodeTag(member_node)) { |
| ... | @@ -13533,6 +12930,10 @@ fn scanContainer( | ... | @@ -13533,6 +12930,10 @@ fn scanContainer( |
| 13533 | .@"struct", .@"opaque" => {}, | 12930 | .@"struct", .@"opaque" => {}, |
| 13534 | .@"union", .@"enum" => full.convertToNonTupleLike(astgen.tree), | 12931 | .@"union", .@"enum" => full.convertToNonTupleLike(astgen.tree), |
| 13535 | } | 12932 | } |
| | 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; |
| 13536 | if (full.ast.tuple_like) continue; | 12937 | if (full.ast.tuple_like) continue; |
| 13537 | break :blk .{ .field, full.ast.main_token }; | 12938 | break :blk .{ .field, full.ast.main_token }; |
| 13538 | }, | 12939 | }, |
| ... | @@ -13698,7 +13099,14 @@ fn scanContainer( | ... | @@ -13698,7 +13099,14 @@ fn scanContainer( |
| 13698 | | 13099 | |
| 13699 | if (!any_duplicates) { | 13100 | if (!any_duplicates) { |
| 13700 | if (any_invalid_declarations) return error.AnalysisFail; | 13101 | 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 | }; |
| 13702 | } | 13110 | } |
| 13703 | | 13111 | |
| 13704 | for (names.keys(), names.values()) |name, first| { | 13112 | for (names.keys(), names.values()) |name, first| { |
| ... | @@ -13954,7 +13362,7 @@ const DeclarationName = union(enum) { | ... | @@ -13954,7 +13362,7 @@ const DeclarationName = union(enum) { |
| 13954 | }; | 13362 | }; |
| 13955 | | 13363 | |
| 13956 | fn addFailedDeclaration( | 13364 | fn addFailedDeclaration( |
| 13957 | wip_members: *WipMembers, | 13365 | wip_decls: *WipDecls, |
| 13958 | gz: *GenZir, | 13366 | gz: *GenZir, |
| 13959 | kind: Zir.Inst.Declaration.Unwrapped.Kind, | 13367 | kind: Zir.Inst.Declaration.Unwrapped.Kind, |
| 13960 | name: Zir.NullTerminatedString, | 13368 | name: Zir.NullTerminatedString, |
| ... | @@ -13962,7 +13370,7 @@ fn addFailedDeclaration( | ... | @@ -13962,7 +13370,7 @@ fn addFailedDeclaration( |
| 13962 | is_pub: bool, | 13370 | is_pub: bool, |
| 13963 | ) !void { | 13371 | ) !void { |
| 13964 | const decl_inst = try gz.makeDeclaration(src_node); | 13372 | const decl_inst = try gz.makeDeclaration(src_node); |
| 13965 | wip_members.nextDecl(decl_inst); | 13373 | wip_decls.nextDecl(decl_inst); |
| 13966 | | 13374 | |
| 13967 | var dummy_gz = gz.makeSubBlock(&gz.base); | 13375 | var dummy_gz = gz.makeSubBlock(&gz.base); |
| 13968 | | 13376 | |