| author | |
| committer | |
| log | a6ca20b9a1dfc7b6e8d004cb166c0714bb8db2db |
| tree | 8ecc7aae4a07f9e5a2fe1d2f2acfe0f40f5ea673 |
| parent | 90ab8ea9e681a4ffac0b4dc500e3ec489014e12f |
| signature |
This changes the representation of closures in Zir and Sema. Rather than
a pair of instructions `closure_capture` and `closure_get`, the system
now works as follows:
* Each ZIR type declaration (`struct_decl` etc) contains a list of
captures in the form of ZIR indices (or, for efficiency, direct
references to parent captures). This is an ordered list; indexes into
it are used to refer to captured values.
* The `extended(closure_get)` ZIR instruction refers to a value in this
list via a 16-bit index (limiting this index to 16 bits allows us to
store this in `extended`).
* `Module.Namespace` has a new field `captures` which contains the list
of values captured in a given namespace. This is initialized based on
the ZIR capture list whenever a type declaration is analyzed.
This change eliminates `CaptureScope` from semantic analysis, which is a
nice simplification; but the main motivation here is that this change is
a prerequisite for #18816.7 files changed, 563 insertions(+), 344 deletions(-)
lib/std/zig/AstGen.zig+149-96| ... | @@ -2205,7 +2205,7 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn | ... | @@ -2205,7 +2205,7 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn |
| 2205 | }, | 2205 | }, |
| 2206 | .local_val => scope = scope.cast(Scope.LocalVal).?.parent, | 2206 | .local_val => scope = scope.cast(Scope.LocalVal).?.parent, |
| 2207 | .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent, | 2207 | .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent, |
| 2208 | .namespace, .enum_namespace => break, | 2208 | .namespace => break, |
| 2209 | .defer_normal, .defer_error => scope = scope.cast(Scope.Defer).?.parent, | 2209 | .defer_normal, .defer_error => scope = scope.cast(Scope.Defer).?.parent, |
| 2210 | .top => unreachable, | 2210 | .top => unreachable, |
| 2211 | } | 2211 | } |
| ... | @@ -2279,7 +2279,7 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) | ... | @@ -2279,7 +2279,7 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) |
| 2279 | try parent_gz.addDefer(defer_scope.index, defer_scope.len); | 2279 | try parent_gz.addDefer(defer_scope.index, defer_scope.len); |
| 2280 | }, | 2280 | }, |
| 2281 | .defer_error => scope = scope.cast(Scope.Defer).?.parent, | 2281 | .defer_error => scope = scope.cast(Scope.Defer).?.parent, |
| 2282 | .namespace, .enum_namespace => break, | 2282 | .namespace => break, |
| 2283 | .top => unreachable, | 2283 | .top => unreachable, |
| 2284 | } | 2284 | } |
| 2285 | } | 2285 | } |
| ... | @@ -2412,7 +2412,7 @@ fn checkLabelRedefinition(astgen: *AstGen, parent_scope: *Scope, label: Ast.Toke | ... | @@ -2412,7 +2412,7 @@ fn checkLabelRedefinition(astgen: *AstGen, parent_scope: *Scope, label: Ast.Toke |
| 2412 | .local_val => scope = scope.cast(Scope.LocalVal).?.parent, | 2412 | .local_val => scope = scope.cast(Scope.LocalVal).?.parent, |
| 2413 | .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent, | 2413 | .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent, |
| 2414 | .defer_normal, .defer_error => scope = scope.cast(Scope.Defer).?.parent, | 2414 | .defer_normal, .defer_error => scope = scope.cast(Scope.Defer).?.parent, |
| 2415 | .namespace, .enum_namespace => break, | 2415 | .namespace => break, |
| 2416 | .top => unreachable, | 2416 | .top => unreachable, |
| 2417 | } | 2417 | } |
| 2418 | } | 2418 | } |
| ... | @@ -2790,7 +2790,6 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As | ... | @@ -2790,7 +2790,6 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As |
| 2790 | .@"resume", | 2790 | .@"resume", |
| 2791 | .@"await", | 2791 | .@"await", |
| 2792 | .ret_err_value_code, | 2792 | .ret_err_value_code, |
| 2793 | .closure_get, | ||
| 2794 | .ret_ptr, | 2793 | .ret_ptr, |
| 2795 | .ret_type, | 2794 | .ret_type, |
| 2796 | .for_len, | 2795 | .for_len, |
| ... | @@ -2860,7 +2859,6 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As | ... | @@ -2860,7 +2859,6 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As |
| 2860 | .store_to_inferred_ptr, | 2859 | .store_to_inferred_ptr, |
| 2861 | .resolve_inferred_alloc, | 2860 | .resolve_inferred_alloc, |
| 2862 | .set_runtime_safety, | 2861 | .set_runtime_safety, |
| 2863 | .closure_capture, | ||
| 2864 | .memcpy, | 2862 | .memcpy, |
| 2865 | .memset, | 2863 | .memset, |
| 2866 | .validate_deref, | 2864 | .validate_deref, |
| ... | @@ -2928,7 +2926,7 @@ fn countDefers(outer_scope: *Scope, inner_scope: *Scope) struct { | ... | @@ -2928,7 +2926,7 @@ fn countDefers(outer_scope: *Scope, inner_scope: *Scope) struct { |
| 2928 | const have_err_payload = defer_scope.remapped_err_code != .none; | 2926 | const have_err_payload = defer_scope.remapped_err_code != .none; |
| 2929 | need_err_code = need_err_code or have_err_payload; | 2927 | need_err_code = need_err_code or have_err_payload; |
| 2930 | }, | 2928 | }, |
| 2931 | .namespace, .enum_namespace => unreachable, | 2929 | .namespace => unreachable, |
| 2932 | .top => unreachable, | 2930 | .top => unreachable, |
| 2933 | } | 2931 | } |
| 2934 | } | 2932 | } |
| ... | @@ -2998,7 +2996,7 @@ fn genDefers( | ... | @@ -2998,7 +2996,7 @@ fn genDefers( |
| 2998 | .normal_only => continue, | 2996 | .normal_only => continue, |
| 2999 | } | 2997 | } |
| 3000 | }, | 2998 | }, |
| 3001 | .namespace, .enum_namespace => unreachable, | 2999 | .namespace => unreachable, |
| 3002 | .top => unreachable, | 3000 | .top => unreachable, |
| 3003 | } | 3001 | } |
| 3004 | } | 3002 | } |
| ... | @@ -3042,7 +3040,7 @@ fn checkUsed(gz: *GenZir, outer_scope: *Scope, inner_scope: *Scope) InnerError!v | ... | @@ -3042,7 +3040,7 @@ fn checkUsed(gz: *GenZir, outer_scope: *Scope, inner_scope: *Scope) InnerError!v |
| 3042 | scope = s.parent; | 3040 | scope = s.parent; |
| 3043 | }, | 3041 | }, |
| 3044 | .defer_normal, .defer_error => scope = scope.cast(Scope.Defer).?.parent, | 3042 | .defer_normal, .defer_error => scope = scope.cast(Scope.Defer).?.parent, |
| 3045 | .namespace, .enum_namespace => unreachable, | 3043 | .namespace => unreachable, |
| 3046 | .top => unreachable, | 3044 | .top => unreachable, |
| 3047 | } | 3045 | } |
| 3048 | } | 3046 | } |
| ... | @@ -4732,7 +4730,7 @@ fn testDecl( | ... | @@ -4732,7 +4730,7 @@ fn testDecl( |
| 4732 | }, | 4730 | }, |
| 4733 | .gen_zir => s = s.cast(GenZir).?.parent, | 4731 | .gen_zir => s = s.cast(GenZir).?.parent, |
| 4734 | .defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent, | 4732 | .defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent, |
| 4735 | .namespace, .enum_namespace => { | 4733 | .namespace => { |
| 4736 | const ns = s.cast(Scope.Namespace).?; | 4734 | const ns = s.cast(Scope.Namespace).?; |
| 4737 | if (ns.decls.get(name_str_index)) |i| { | 4735 | if (ns.decls.get(name_str_index)) |i| { |
| 4738 | if (found_already) |f| { | 4736 | if (found_already) |f| { |
| ... | @@ -4849,10 +4847,10 @@ fn structDeclInner( | ... | @@ -4849,10 +4847,10 @@ fn structDeclInner( |
| 4849 | try gz.setStruct(decl_inst, .{ | 4847 | try gz.setStruct(decl_inst, .{ |
| 4850 | .src_node = node, | 4848 | .src_node = node, |
| 4851 | .layout = layout, | 4849 | .layout = layout, |
| 4850 | .captures_len = 0, | ||
| 4852 | .fields_len = 0, | 4851 | .fields_len = 0, |
| 4853 | .decls_len = 0, | 4852 | .decls_len = 0, |
| 4854 | .backing_int_ref = .none, | 4853 | .has_backing_int = false, |
| 4855 | .backing_int_body_len = 0, | ||
| 4856 | .known_non_opv = false, | 4854 | .known_non_opv = false, |
| 4857 | .known_comptime_only = false, | 4855 | .known_comptime_only = false, |
| 4858 | .is_tuple = false, | 4856 | .is_tuple = false, |
| ... | @@ -5142,10 +5140,10 @@ fn structDeclInner( | ... | @@ -5142,10 +5140,10 @@ fn structDeclInner( |
| 5142 | try gz.setStruct(decl_inst, .{ | 5140 | try gz.setStruct(decl_inst, .{ |
| 5143 | .src_node = node, | 5141 | .src_node = node, |
| 5144 | .layout = layout, | 5142 | .layout = layout, |
| 5143 | .captures_len = @intCast(namespace.captures.count()), | ||
| 5145 | .fields_len = field_count, | 5144 | .fields_len = field_count, |
| 5146 | .decls_len = decl_count, | 5145 | .decls_len = decl_count, |
| 5147 | .backing_int_ref = backing_int_ref, | 5146 | .has_backing_int = backing_int_ref != .none, |
| 5148 | .backing_int_body_len = @intCast(backing_int_body_len), | ||
| 5149 | .known_non_opv = known_non_opv, | 5147 | .known_non_opv = known_non_opv, |
| 5150 | .known_comptime_only = known_comptime_only, | 5148 | .known_comptime_only = known_comptime_only, |
| 5151 | .is_tuple = is_tuple, | 5149 | .is_tuple = is_tuple, |
| ... | @@ -5159,15 +5157,22 @@ fn structDeclInner( | ... | @@ -5159,15 +5157,22 @@ fn structDeclInner( |
| 5159 | const decls_slice = wip_members.declsSlice(); | 5157 | const decls_slice = wip_members.declsSlice(); |
| 5160 | const fields_slice = wip_members.fieldsSlice(); | 5158 | const fields_slice = wip_members.fieldsSlice(); |
| 5161 | const bodies_slice = astgen.scratch.items[bodies_start..]; | 5159 | const bodies_slice = astgen.scratch.items[bodies_start..]; |
| 5162 | try astgen.extra.ensureUnusedCapacity(gpa, backing_int_body_len + | 5160 | try astgen.extra.ensureUnusedCapacity(gpa, backing_int_body_len + 2 + |
| 5163 | decls_slice.len + fields_slice.len + bodies_slice.len); | 5161 | decls_slice.len + namespace.captures.count() + fields_slice.len + bodies_slice.len); |
| 5164 | astgen.extra.appendSliceAssumeCapacity(astgen.scratch.items[scratch_top..][0..backing_int_body_len]); | 5162 | astgen.extra.appendSliceAssumeCapacity(@ptrCast(namespace.captures.keys())); |
| 5163 | if (backing_int_ref != .none) { | ||
| 5164 | astgen.extra.appendAssumeCapacity(@intCast(backing_int_body_len)); | ||
| 5165 | if (backing_int_body_len == 0) { | ||
| 5166 | astgen.extra.appendAssumeCapacity(@intFromEnum(backing_int_ref)); | ||
| 5167 | } else { | ||
| 5168 | astgen.extra.appendSliceAssumeCapacity(astgen.scratch.items[scratch_top..][0..backing_int_body_len]); | ||
| 5169 | } | ||
| 5170 | } | ||
| 5165 | astgen.extra.appendSliceAssumeCapacity(decls_slice); | 5171 | astgen.extra.appendSliceAssumeCapacity(decls_slice); |
| 5166 | astgen.extra.appendSliceAssumeCapacity(fields_slice); | 5172 | astgen.extra.appendSliceAssumeCapacity(fields_slice); |
| 5167 | astgen.extra.appendSliceAssumeCapacity(bodies_slice); | 5173 | astgen.extra.appendSliceAssumeCapacity(bodies_slice); |
| 5168 | 5174 | ||
| 5169 | block_scope.unstack(); | 5175 | block_scope.unstack(); |
| 5170 | try gz.addNamespaceCaptures(&namespace); | ||
| 5171 | return decl_inst.toRef(); | 5176 | return decl_inst.toRef(); |
| 5172 | } | 5177 | } |
| 5173 | 5178 | ||
| ... | @@ -5368,6 +5373,7 @@ fn unionDeclInner( | ... | @@ -5368,6 +5373,7 @@ fn unionDeclInner( |
| 5368 | .src_node = node, | 5373 | .src_node = node, |
| 5369 | .layout = layout, | 5374 | .layout = layout, |
| 5370 | .tag_type = arg_inst, | 5375 | .tag_type = arg_inst, |
| 5376 | .captures_len = @intCast(namespace.captures.count()), | ||
| 5371 | .body_len = body_len, | 5377 | .body_len = body_len, |
| 5372 | .fields_len = field_count, | 5378 | .fields_len = field_count, |
| 5373 | .decls_len = decl_count, | 5379 | .decls_len = decl_count, |
| ... | @@ -5379,13 +5385,13 @@ fn unionDeclInner( | ... | @@ -5379,13 +5385,13 @@ fn unionDeclInner( |
| 5379 | wip_members.finishBits(bits_per_field); | 5385 | wip_members.finishBits(bits_per_field); |
| 5380 | const decls_slice = wip_members.declsSlice(); | 5386 | const decls_slice = wip_members.declsSlice(); |
| 5381 | const fields_slice = wip_members.fieldsSlice(); | 5387 | const fields_slice = wip_members.fieldsSlice(); |
| 5382 | try astgen.extra.ensureUnusedCapacity(gpa, decls_slice.len + body_len + fields_slice.len); | 5388 | try astgen.extra.ensureUnusedCapacity(gpa, namespace.captures.count() + decls_slice.len + body_len + fields_slice.len); |
| 5389 | astgen.extra.appendSliceAssumeCapacity(@ptrCast(namespace.captures.keys())); | ||
| 5383 | astgen.extra.appendSliceAssumeCapacity(decls_slice); | 5390 | astgen.extra.appendSliceAssumeCapacity(decls_slice); |
| 5384 | astgen.appendBodyWithFixups(body); | 5391 | astgen.appendBodyWithFixups(body); |
| 5385 | astgen.extra.appendSliceAssumeCapacity(fields_slice); | 5392 | astgen.extra.appendSliceAssumeCapacity(fields_slice); |
| 5386 | 5393 | ||
| 5387 | block_scope.unstack(); | 5394 | block_scope.unstack(); |
| 5388 | try gz.addNamespaceCaptures(&namespace); | ||
| 5389 | return decl_inst.toRef(); | 5395 | return decl_inst.toRef(); |
| 5390 | } | 5396 | } |
| 5391 | 5397 | ||
| ... | @@ -5555,7 +5561,7 @@ fn containerDecl( | ... | @@ -5555,7 +5561,7 @@ fn containerDecl( |
| 5555 | defer block_scope.unstack(); | 5561 | defer block_scope.unstack(); |
| 5556 | 5562 | ||
| 5557 | _ = try astgen.scanDecls(&namespace, container_decl.ast.members); | 5563 | _ = try astgen.scanDecls(&namespace, container_decl.ast.members); |
| 5558 | namespace.base.tag = .enum_namespace; | 5564 | namespace.base.tag = .namespace; |
| 5559 | 5565 | ||
| 5560 | const arg_inst: Zir.Inst.Ref = if (container_decl.ast.arg != 0) | 5566 | const arg_inst: Zir.Inst.Ref = if (container_decl.ast.arg != 0) |
| 5561 | try comptimeExpr(&block_scope, &namespace.base, coerced_type_ri, container_decl.ast.arg) | 5567 | try comptimeExpr(&block_scope, &namespace.base, coerced_type_ri, container_decl.ast.arg) |
| ... | @@ -5586,7 +5592,6 @@ fn containerDecl( | ... | @@ -5586,7 +5592,6 @@ fn containerDecl( |
| 5586 | if (member_node == counts.nonexhaustive_node) | 5592 | if (member_node == counts.nonexhaustive_node) |
| 5587 | continue; | 5593 | continue; |
| 5588 | fields_hasher.update(tree.getNodeSource(member_node)); | 5594 | fields_hasher.update(tree.getNodeSource(member_node)); |
| 5589 | namespace.base.tag = .namespace; | ||
| 5590 | var member = switch (try containerMember(&block_scope, &namespace.base, &wip_members, member_node)) { | 5595 | var member = switch (try containerMember(&block_scope, &namespace.base, &wip_members, member_node)) { |
| 5591 | .decl => continue, | 5596 | .decl => continue, |
| 5592 | .field => |field| field, | 5597 | .field => |field| field, |
| ... | @@ -5630,7 +5635,6 @@ fn containerDecl( | ... | @@ -5630,7 +5635,6 @@ fn containerDecl( |
| 5630 | }, | 5635 | }, |
| 5631 | ); | 5636 | ); |
| 5632 | } | 5637 | } |
| 5633 | namespace.base.tag = .enum_namespace; | ||
| 5634 | const tag_value_inst = try expr(&block_scope, &namespace.base, .{ .rl = .{ .ty = arg_inst } }, member.ast.value_expr); | 5638 | const tag_value_inst = try expr(&block_scope, &namespace.base, .{ .rl = .{ .ty = arg_inst } }, member.ast.value_expr); |
| 5635 | wip_members.appendToField(@intFromEnum(tag_value_inst)); | 5639 | wip_members.appendToField(@intFromEnum(tag_value_inst)); |
| 5636 | } | 5640 | } |
| ... | @@ -5676,6 +5680,7 @@ fn containerDecl( | ... | @@ -5676,6 +5680,7 @@ fn containerDecl( |
| 5676 | .src_node = node, | 5680 | .src_node = node, |
| 5677 | .nonexhaustive = nonexhaustive, | 5681 | .nonexhaustive = nonexhaustive, |
| 5678 | .tag_type = arg_inst, | 5682 | .tag_type = arg_inst, |
| 5683 | .captures_len = @intCast(namespace.captures.count()), | ||
| 5679 | .body_len = body_len, | 5684 | .body_len = body_len, |
| 5680 | .fields_len = @intCast(counts.total_fields), | 5685 | .fields_len = @intCast(counts.total_fields), |
| 5681 | .decls_len = @intCast(counts.decls), | 5686 | .decls_len = @intCast(counts.decls), |
| ... | @@ -5685,13 +5690,13 @@ fn containerDecl( | ... | @@ -5685,13 +5690,13 @@ fn containerDecl( |
| 5685 | wip_members.finishBits(bits_per_field); | 5690 | wip_members.finishBits(bits_per_field); |
| 5686 | const decls_slice = wip_members.declsSlice(); | 5691 | const decls_slice = wip_members.declsSlice(); |
| 5687 | const fields_slice = wip_members.fieldsSlice(); | 5692 | const fields_slice = wip_members.fieldsSlice(); |
| 5688 | try astgen.extra.ensureUnusedCapacity(gpa, decls_slice.len + body_len + fields_slice.len); | 5693 | try astgen.extra.ensureUnusedCapacity(gpa, namespace.captures.count() + decls_slice.len + body_len + fields_slice.len); |
| 5694 | astgen.extra.appendSliceAssumeCapacity(@ptrCast(namespace.captures.keys())); | ||
| 5689 | astgen.extra.appendSliceAssumeCapacity(decls_slice); | 5695 | astgen.extra.appendSliceAssumeCapacity(decls_slice); |
| 5690 | astgen.appendBodyWithFixups(body); | 5696 | astgen.appendBodyWithFixups(body); |
| 5691 | astgen.extra.appendSliceAssumeCapacity(fields_slice); | 5697 | astgen.extra.appendSliceAssumeCapacity(fields_slice); |
| 5692 | 5698 | ||
| 5693 | block_scope.unstack(); | 5699 | block_scope.unstack(); |
| 5694 | try gz.addNamespaceCaptures(&namespace); | ||
| 5695 | return rvalue(gz, ri, decl_inst.toRef(), node); | 5700 | return rvalue(gz, ri, decl_inst.toRef(), node); |
| 5696 | }, | 5701 | }, |
| 5697 | .keyword_opaque => { | 5702 | .keyword_opaque => { |
| ... | @@ -5733,16 +5738,17 @@ fn containerDecl( | ... | @@ -5733,16 +5738,17 @@ fn containerDecl( |
| 5733 | 5738 | ||
| 5734 | try gz.setOpaque(decl_inst, .{ | 5739 | try gz.setOpaque(decl_inst, .{ |
| 5735 | .src_node = node, | 5740 | .src_node = node, |
| 5741 | .captures_len = @intCast(namespace.captures.count()), | ||
| 5736 | .decls_len = decl_count, | 5742 | .decls_len = decl_count, |
| 5737 | }); | 5743 | }); |
| 5738 | 5744 | ||
| 5739 | wip_members.finishBits(0); | 5745 | wip_members.finishBits(0); |
| 5740 | const decls_slice = wip_members.declsSlice(); | 5746 | const decls_slice = wip_members.declsSlice(); |
| 5741 | try astgen.extra.ensureUnusedCapacity(gpa, decls_slice.len); | 5747 | try astgen.extra.ensureUnusedCapacity(gpa, namespace.captures.count() + decls_slice.len); |
| 5748 | astgen.extra.appendSliceAssumeCapacity(@ptrCast(namespace.captures.keys())); | ||
| 5742 | astgen.extra.appendSliceAssumeCapacity(decls_slice); | 5749 | astgen.extra.appendSliceAssumeCapacity(decls_slice); |
| 5743 | 5750 | ||
| 5744 | block_scope.unstack(); | 5751 | block_scope.unstack(); |
| 5745 | try gz.addNamespaceCaptures(&namespace); | ||
| 5746 | return rvalue(gz, ri, decl_inst.toRef(), node); | 5752 | return rvalue(gz, ri, decl_inst.toRef(), node); |
| 5747 | }, | 5753 | }, |
| 5748 | else => unreachable, | 5754 | else => unreachable, |
| ... | @@ -8238,12 +8244,12 @@ fn localVarRef( | ... | @@ -8238,12 +8244,12 @@ fn localVarRef( |
| 8238 | ident_token: Ast.TokenIndex, | 8244 | ident_token: Ast.TokenIndex, |
| 8239 | ) InnerError!Zir.Inst.Ref { | 8245 | ) InnerError!Zir.Inst.Ref { |
| 8240 | const astgen = gz.astgen; | 8246 | const astgen = gz.astgen; |
| 8241 | const gpa = astgen.gpa; | ||
| 8242 | const name_str_index = try astgen.identAsString(ident_token); | 8247 | const name_str_index = try astgen.identAsString(ident_token); |
| 8243 | var s = scope; | 8248 | var s = scope; |
| 8244 | var found_already: ?Ast.Node.Index = null; // we have found a decl with the same name already | 8249 | var found_already: ?Ast.Node.Index = null; // we have found a decl with the same name already |
| 8245 | var num_namespaces_out: u32 = 0; | 8250 | var num_namespaces_out: u32 = 0; |
| 8246 | var capturing_namespace: ?*Scope.Namespace = null; | 8251 | // defined when `num_namespaces_out != 0` |
| 8252 | var capturing_namespace: *Scope.Namespace = undefined; | ||
| 8247 | while (true) switch (s.tag) { | 8253 | while (true) switch (s.tag) { |
| 8248 | .local_val => { | 8254 | .local_val => { |
| 8249 | const local_val = s.cast(Scope.LocalVal).?; | 8255 | const local_val = s.cast(Scope.LocalVal).?; |
| ... | @@ -8257,15 +8263,14 @@ fn localVarRef( | ... | @@ -8257,15 +8263,14 @@ fn localVarRef( |
| 8257 | local_val.used = ident_token; | 8263 | local_val.used = ident_token; |
| 8258 | } | 8264 | } |
| 8259 | 8265 | ||
| 8260 | const value_inst = try tunnelThroughClosure( | 8266 | const value_inst = if (num_namespaces_out != 0) try tunnelThroughClosure( |
| 8261 | gz, | 8267 | gz, |
| 8262 | ident, | 8268 | ident, |
| 8263 | num_namespaces_out, | 8269 | num_namespaces_out, |
| 8264 | capturing_namespace, | 8270 | capturing_namespace, |
| 8265 | local_val.inst, | 8271 | local_val.inst, |
| 8266 | local_val.token_src, | 8272 | local_val.token_src, |
| 8267 | gpa, | 8273 | ) else local_val.inst; |
| 8268 | ); | ||
| 8269 | 8274 | ||
| 8270 | return rvalueNoCoercePreRef(gz, ri, value_inst, ident); | 8275 | return rvalueNoCoercePreRef(gz, ri, value_inst, ident); |
| 8271 | } | 8276 | } |
| ... | @@ -8285,19 +8290,18 @@ fn localVarRef( | ... | @@ -8285,19 +8290,18 @@ fn localVarRef( |
| 8285 | const ident_name = try astgen.identifierTokenString(ident_token); | 8290 | const ident_name = try astgen.identifierTokenString(ident_token); |
| 8286 | return astgen.failNodeNotes(ident, "mutable '{s}' not accessible from here", .{ident_name}, &.{ | 8291 | return astgen.failNodeNotes(ident, "mutable '{s}' not accessible from here", .{ident_name}, &.{ |
| 8287 | try astgen.errNoteTok(local_ptr.token_src, "declared mutable here", .{}), | 8292 | try astgen.errNoteTok(local_ptr.token_src, "declared mutable here", .{}), |
| 8288 | try astgen.errNoteNode(capturing_namespace.?.node, "crosses namespace boundary here", .{}), | 8293 | try astgen.errNoteNode(capturing_namespace.node, "crosses namespace boundary here", .{}), |
| 8289 | }); | 8294 | }); |
| 8290 | } | 8295 | } |
| 8291 | 8296 | ||
| 8292 | const ptr_inst = try tunnelThroughClosure( | 8297 | const ptr_inst = if (num_namespaces_out != 0) try tunnelThroughClosure( |
| 8293 | gz, | 8298 | gz, |
| 8294 | ident, | 8299 | ident, |
| 8295 | num_namespaces_out, | 8300 | num_namespaces_out, |
| 8296 | capturing_namespace, | 8301 | capturing_namespace, |
| 8297 | local_ptr.ptr, | 8302 | local_ptr.ptr, |
| 8298 | local_ptr.token_src, | 8303 | local_ptr.token_src, |
| 8299 | gpa, | 8304 | ) else local_ptr.ptr; |
| 8300 | ); | ||
| 8301 | 8305 | ||
| 8302 | switch (ri.rl) { | 8306 | switch (ri.rl) { |
| 8303 | .ref, .ref_coerced_ty => { | 8307 | .ref, .ref_coerced_ty => { |
| ... | @@ -8314,7 +8318,7 @@ fn localVarRef( | ... | @@ -8314,7 +8318,7 @@ fn localVarRef( |
| 8314 | }, | 8318 | }, |
| 8315 | .gen_zir => s = s.cast(GenZir).?.parent, | 8319 | .gen_zir => s = s.cast(GenZir).?.parent, |
| 8316 | .defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent, | 8320 | .defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent, |
| 8317 | .namespace, .enum_namespace => { | 8321 | .namespace => { |
| 8318 | const ns = s.cast(Scope.Namespace).?; | 8322 | const ns = s.cast(Scope.Namespace).?; |
| 8319 | if (ns.decls.get(name_str_index)) |i| { | 8323 | if (ns.decls.get(name_str_index)) |i| { |
| 8320 | if (found_already) |f| { | 8324 | if (found_already) |f| { |
| ... | @@ -8326,7 +8330,7 @@ fn localVarRef( | ... | @@ -8326,7 +8330,7 @@ fn localVarRef( |
| 8326 | // We found a match but must continue looking for ambiguous references to decls. | 8330 | // We found a match but must continue looking for ambiguous references to decls. |
| 8327 | found_already = i; | 8331 | found_already = i; |
| 8328 | } | 8332 | } |
| 8329 | if (s.tag == .namespace) num_namespaces_out += 1; | 8333 | num_namespaces_out += 1; |
| 8330 | capturing_namespace = ns; | 8334 | capturing_namespace = ns; |
| 8331 | s = ns.parent; | 8335 | s = ns.parent; |
| 8332 | }, | 8336 | }, |
| ... | @@ -8348,41 +8352,70 @@ fn localVarRef( | ... | @@ -8348,41 +8352,70 @@ fn localVarRef( |
| 8348 | } | 8352 | } |
| 8349 | } | 8353 | } |
| 8350 | 8354 | ||
| 8351 | /// Adds a capture to a namespace, if needed. | 8355 | /// Access a ZIR instruction through closure. May tunnel through arbitrarily |
| 8352 | /// Returns the index of the closure_capture instruction. | 8356 | /// many namespaces, adding closure captures as required. |
| 8357 | /// Returns the index of the `closure_get` instruction added to `gz`. | ||
| 8353 | fn tunnelThroughClosure( | 8358 | fn tunnelThroughClosure( |
| 8354 | gz: *GenZir, | 8359 | gz: *GenZir, |
| 8360 | /// The node which references the value to be captured. | ||
| 8355 | inner_ref_node: Ast.Node.Index, | 8361 | inner_ref_node: Ast.Node.Index, |
| 8362 | /// The number of namespaces being tunnelled through. At least 1. | ||
| 8356 | num_tunnels: u32, | 8363 | num_tunnels: u32, |
| 8357 | ns: ?*Scope.Namespace, | 8364 | /// The namespace being captured from. |
| 8365 | ns: *Scope.Namespace, | ||
| 8366 | /// The value being captured. | ||
| 8358 | value: Zir.Inst.Ref, | 8367 | value: Zir.Inst.Ref, |
| 8368 | /// The token of the value's declaration. | ||
| 8359 | token: Ast.TokenIndex, | 8369 | token: Ast.TokenIndex, |
| 8360 | gpa: Allocator, | ||
| 8361 | ) !Zir.Inst.Ref { | 8370 | ) !Zir.Inst.Ref { |
| 8362 | // For trivial values, we don't need a tunnel. | 8371 | const value_inst = value.toIndex() orelse { |
| 8363 | // Just return the ref. | 8372 | // For trivial values, we don't need a tunnel; just return the ref. |
| 8364 | if (num_tunnels == 0 or value.toIndex() == null) { | ||
| 8365 | return value; | 8373 | return value; |
| 8374 | }; | ||
| 8375 | |||
| 8376 | const astgen = gz.astgen; | ||
| 8377 | const gpa = astgen.gpa; | ||
| 8378 | |||
| 8379 | // Otherwise we need a tunnel. First, figure out the path of namespaces we | ||
| 8380 | // are tunneling through. This is usually only going to be one or two, so | ||
| 8381 | // use an SFBA to optimize for the common case. | ||
| 8382 | var sfba = std.heap.stackFallback(@sizeOf(usize) * 2, astgen.arena); | ||
| 8383 | var intermediate_tunnels = try sfba.get().alloc(*Scope.Namespace, num_tunnels - 1); | ||
| 8384 | |||
| 8385 | { | ||
| 8386 | var i: usize = num_tunnels - 1; | ||
| 8387 | var scope: *Scope = gz.parent; | ||
| 8388 | while (i > 0) { | ||
| 8389 | if (scope.cast(Scope.Namespace)) |mid_ns| { | ||
| 8390 | i -= 1; | ||
| 8391 | intermediate_tunnels[i] = mid_ns; | ||
| 8392 | } | ||
| 8393 | scope = scope.parent().?; | ||
| 8394 | } | ||
| 8366 | } | 8395 | } |
| 8367 | 8396 | ||
| 8368 | // Otherwise we need a tunnel. Check if this namespace | 8397 | // Now that we know the scopes we're tunneling through, begin adding |
| 8369 | // already has one for this value. | 8398 | // captures as required, starting with the outermost namespace. |
| 8370 | const gop = try ns.?.captures.getOrPut(gpa, value.toIndex().?); | 8399 | var cur_capture_index = std.math.cast( |
| 8371 | if (!gop.found_existing) { | 8400 | u16, |
| 8372 | // Make a new capture for this value but don't add it to the declaring_gz yet | 8401 | (try ns.captures.getOrPut(gpa, Zir.Inst.Capture.wrap(.{ .inst = value_inst }))).index, |
| 8373 | try gz.astgen.instructions.append(gz.astgen.gpa, .{ | 8402 | ) orelse return astgen.failNodeNotes(ns.node, "this compiler implementation only supports up to 65536 captures per namespace", .{}, &.{ |
| 8374 | .tag = .closure_capture, | 8403 | try astgen.errNoteTok(token, "captured value here", .{}), |
| 8375 | .data = .{ .un_tok = .{ | 8404 | try astgen.errNoteNode(inner_ref_node, "value used here", .{}), |
| 8376 | .operand = value, | 8405 | }); |
| 8377 | .src_tok = ns.?.declaring_gz.?.tokenIndexToRelative(token), | 8406 | |
| 8378 | } }, | 8407 | for (intermediate_tunnels) |tunnel_ns| { |
| 8408 | cur_capture_index = std.math.cast( | ||
| 8409 | u16, | ||
| 8410 | (try tunnel_ns.captures.getOrPut(gpa, Zir.Inst.Capture.wrap(.{ .nested = cur_capture_index }))).index, | ||
| 8411 | ) orelse return astgen.failNodeNotes(tunnel_ns.node, "this compiler implementation only supports up to 65536 captures per namespace", .{}, &.{ | ||
| 8412 | try astgen.errNoteTok(token, "captured value here", .{}), | ||
| 8413 | try astgen.errNoteNode(inner_ref_node, "value used here", .{}), | ||
| 8379 | }); | 8414 | }); |
| 8380 | gop.value_ptr.* = @enumFromInt(gz.astgen.instructions.len - 1); | ||
| 8381 | } | 8415 | } |
| 8382 | 8416 | ||
| 8383 | // Add an instruction to get the value from the closure into | 8417 | // Add an instruction to get the value from the closure. |
| 8384 | // our current context | 8418 | return gz.addExtendedNodeSmall(.closure_get, inner_ref_node, cur_capture_index); |
| 8385 | return try gz.addInstNode(.closure_get, gop.value_ptr.*, inner_ref_node); | ||
| 8386 | } | 8419 | } |
| 8387 | 8420 | ||
| 8388 | fn stringLiteral( | 8421 | fn stringLiteral( |
| ... | @@ -9095,7 +9128,7 @@ fn builtinCall( | ... | @@ -9095,7 +9128,7 @@ fn builtinCall( |
| 9095 | }, | 9128 | }, |
| 9096 | .gen_zir => s = s.cast(GenZir).?.parent, | 9129 | .gen_zir => s = s.cast(GenZir).?.parent, |
| 9097 | .defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent, | 9130 | .defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent, |
| 9098 | .namespace, .enum_namespace => { | 9131 | .namespace => { |
| 9099 | const ns = s.cast(Scope.Namespace).?; | 9132 | const ns = s.cast(Scope.Namespace).?; |
| 9100 | if (ns.decls.get(decl_name)) |i| { | 9133 | if (ns.decls.get(decl_name)) |i| { |
| 9101 | if (found_already) |f| { | 9134 | if (found_already) |f| { |
| ... | @@ -11605,7 +11638,7 @@ const Scope = struct { | ... | @@ -11605,7 +11638,7 @@ const Scope = struct { |
| 11605 | } | 11638 | } |
| 11606 | if (T == Namespace) { | 11639 | if (T == Namespace) { |
| 11607 | switch (base.tag) { | 11640 | switch (base.tag) { |
| 11608 | .namespace, .enum_namespace => return @fieldParentPtr(T, "base", base), | 11641 | .namespace => return @fieldParentPtr(T, "base", base), |
| 11609 | else => return null, | 11642 | else => return null, |
| 11610 | } | 11643 | } |
| 11611 | } | 11644 | } |
| ... | @@ -11621,7 +11654,7 @@ const Scope = struct { | ... | @@ -11621,7 +11654,7 @@ const Scope = struct { |
| 11621 | .local_val => base.cast(LocalVal).?.parent, | 11654 | .local_val => base.cast(LocalVal).?.parent, |
| 11622 | .local_ptr => base.cast(LocalPtr).?.parent, | 11655 | .local_ptr => base.cast(LocalPtr).?.parent, |
| 11623 | .defer_normal, .defer_error => base.cast(Defer).?.parent, | 11656 | .defer_normal, .defer_error => base.cast(Defer).?.parent, |
| 11624 | .namespace, .enum_namespace => base.cast(Namespace).?.parent, | 11657 | .namespace => base.cast(Namespace).?.parent, |
| 11625 | .top => null, | 11658 | .top => null, |
| 11626 | }; | 11659 | }; |
| 11627 | } | 11660 | } |
| ... | @@ -11633,7 +11666,6 @@ const Scope = struct { | ... | @@ -11633,7 +11666,6 @@ const Scope = struct { |
| 11633 | defer_normal, | 11666 | defer_normal, |
| 11634 | defer_error, | 11667 | defer_error, |
| 11635 | namespace, | 11668 | namespace, |
| 11636 | enum_namespace, | ||
| 11637 | top, | 11669 | top, |
| 11638 | }; | 11670 | }; |
| 11639 | 11671 | ||
| ... | @@ -11725,9 +11757,8 @@ const Scope = struct { | ... | @@ -11725,9 +11757,8 @@ const Scope = struct { |
| 11725 | /// Only valid during astgen. | 11757 | /// Only valid during astgen. |
| 11726 | declaring_gz: ?*GenZir, | 11758 | declaring_gz: ?*GenZir, |
| 11727 | 11759 | ||
| 11728 | /// Map from the raw captured value to the instruction | 11760 | /// Set of captures used by this namespace. |
| 11729 | /// ref of the capture for decls in this namespace | 11761 | captures: std.AutoArrayHashMapUnmanaged(Zir.Inst.Capture, void) = .{}, |
| 11730 | captures: std.AutoArrayHashMapUnmanaged(Zir.Inst.Index, Zir.Inst.Index) = .{}, | ||
| 11731 | 11762 | ||
| 11732 | fn deinit(self: *Namespace, gpa: Allocator) void { | 11763 | fn deinit(self: *Namespace, gpa: Allocator) void { |
| 11733 | self.decls.deinit(gpa); | 11764 | self.decls.deinit(gpa); |
| ... | @@ -11787,12 +11818,6 @@ const GenZir = struct { | ... | @@ -11787,12 +11818,6 @@ const GenZir = struct { |
| 11787 | // Set if this GenZir is a defer or it is inside a defer. | 11818 | // Set if this GenZir is a defer or it is inside a defer. |
| 11788 | any_defer_node: Ast.Node.Index = 0, | 11819 | any_defer_node: Ast.Node.Index = 0, |
| 11789 | 11820 | ||
| 11790 | /// Namespace members are lazy. When executing a decl within a namespace, | ||
| 11791 | /// any references to external instructions need to be treated specially. | ||
| 11792 | /// This list tracks those references. See also .closure_capture and .closure_get. | ||
| 11793 | /// Keys are the raw instruction index, values are the closure_capture instruction. | ||
| 11794 | captures: std.AutoHashMapUnmanaged(Zir.Inst.Index, Zir.Inst.Index) = .{}, | ||
| 11795 | |||
| 11796 | const unstacked_top = std.math.maxInt(usize); | 11821 | const unstacked_top = std.math.maxInt(usize); |
| 11797 | /// Call unstack before adding any new instructions to containing GenZir. | 11822 | /// Call unstack before adding any new instructions to containing GenZir. |
| 11798 | fn unstack(self: *GenZir) void { | 11823 | fn unstack(self: *GenZir) void { |
| ... | @@ -12534,6 +12559,30 @@ const GenZir = struct { | ... | @@ -12534,6 +12559,30 @@ const GenZir = struct { |
| 12534 | return new_index.toRef(); | 12559 | return new_index.toRef(); |
| 12535 | } | 12560 | } |
| 12536 | 12561 | ||
| 12562 | fn addExtendedNodeSmall( | ||
| 12563 | gz: *GenZir, | ||
| 12564 | opcode: Zir.Inst.Extended, | ||
| 12565 | src_node: Ast.Node.Index, | ||
| 12566 | small: u16, | ||
| 12567 | ) !Zir.Inst.Ref { | ||
| 12568 | const astgen = gz.astgen; | ||
| 12569 | const gpa = astgen.gpa; | ||
| 12570 | |||
| 12571 | try gz.instructions.ensureUnusedCapacity(gpa, 1); | ||
| 12572 | try astgen.instructions.ensureUnusedCapacity(gpa, 1); | ||
| 12573 | const new_index: Zir.Inst.Index = @enumFromInt(astgen.instructions.len); | ||
| 12574 | astgen.instructions.appendAssumeCapacity(.{ | ||
| 12575 | .tag = .extended, | ||
| 12576 | .data = .{ .extended = .{ | ||
| 12577 | .opcode = opcode, | ||
| 12578 | .small = small, | ||
| 12579 | .operand = @bitCast(gz.nodeIndexToRelative(src_node)), | ||
| 12580 | } }, | ||
| 12581 | }); | ||
| 12582 | gz.instructions.appendAssumeCapacity(new_index); | ||
| 12583 | return new_index.toRef(); | ||
| 12584 | } | ||
| 12585 | |||
| 12537 | fn addUnTok( | 12586 | fn addUnTok( |
| 12538 | gz: *GenZir, | 12587 | gz: *GenZir, |
| 12539 | tag: Zir.Inst.Tag, | 12588 | tag: Zir.Inst.Tag, |
| ... | @@ -12957,10 +13006,10 @@ const GenZir = struct { | ... | @@ -12957,10 +13006,10 @@ const GenZir = struct { |
| 12957 | 13006 | ||
| 12958 | fn setStruct(gz: *GenZir, inst: Zir.Inst.Index, args: struct { | 13007 | fn setStruct(gz: *GenZir, inst: Zir.Inst.Index, args: struct { |
| 12959 | src_node: Ast.Node.Index, | 13008 | src_node: Ast.Node.Index, |
| 13009 | captures_len: u32, | ||
| 12960 | fields_len: u32, | 13010 | fields_len: u32, |
| 12961 | decls_len: u32, | 13011 | decls_len: u32, |
| 12962 | backing_int_ref: Zir.Inst.Ref, | 13012 | has_backing_int: bool, |
| 12963 | backing_int_body_len: u32, | ||
| 12964 | layout: std.builtin.Type.ContainerLayout, | 13013 | layout: std.builtin.Type.ContainerLayout, |
| 12965 | known_non_opv: bool, | 13014 | known_non_opv: bool, |
| 12966 | known_comptime_only: bool, | 13015 | known_comptime_only: bool, |
| ... | @@ -12978,7 +13027,7 @@ const GenZir = struct { | ... | @@ -12978,7 +13027,7 @@ const GenZir = struct { |
| 12978 | 13027 | ||
| 12979 | const fields_hash_arr: [4]u32 = @bitCast(args.fields_hash); | 13028 | const fields_hash_arr: [4]u32 = @bitCast(args.fields_hash); |
| 12980 | 13029 | ||
| 12981 | try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.StructDecl).Struct.fields.len + 4); | 13030 | try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.StructDecl).Struct.fields.len + 3); |
| 12982 | const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.StructDecl{ | 13031 | const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.StructDecl{ |
| 12983 | .fields_hash_0 = fields_hash_arr[0], | 13032 | .fields_hash_0 = fields_hash_arr[0], |
| 12984 | .fields_hash_1 = fields_hash_arr[1], | 13033 | .fields_hash_1 = fields_hash_arr[1], |
| ... | @@ -12987,26 +13036,24 @@ const GenZir = struct { | ... | @@ -12987,26 +13036,24 @@ const GenZir = struct { |
| 12987 | .src_node = gz.nodeIndexToRelative(args.src_node), | 13036 | .src_node = gz.nodeIndexToRelative(args.src_node), |
| 12988 | }); | 13037 | }); |
| 12989 | 13038 | ||
| 13039 | if (args.captures_len != 0) { | ||
| 13040 | astgen.extra.appendAssumeCapacity(args.captures_len); | ||
| 13041 | } | ||
| 12990 | if (args.fields_len != 0) { | 13042 | if (args.fields_len != 0) { |
| 12991 | astgen.extra.appendAssumeCapacity(args.fields_len); | 13043 | astgen.extra.appendAssumeCapacity(args.fields_len); |
| 12992 | } | 13044 | } |
| 12993 | if (args.decls_len != 0) { | 13045 | if (args.decls_len != 0) { |
| 12994 | astgen.extra.appendAssumeCapacity(args.decls_len); | 13046 | astgen.extra.appendAssumeCapacity(args.decls_len); |
| 12995 | } | 13047 | } |
| 12996 | if (args.backing_int_ref != .none) { | ||
| 12997 | astgen.extra.appendAssumeCapacity(args.backing_int_body_len); | ||
| 12998 | if (args.backing_int_body_len == 0) { | ||
| 12999 | astgen.extra.appendAssumeCapacity(@intFromEnum(args.backing_int_ref)); | ||
| 13000 | } | ||
| 13001 | } | ||
| 13002 | astgen.instructions.set(@intFromEnum(inst), .{ | 13048 | astgen.instructions.set(@intFromEnum(inst), .{ |
| 13003 | .tag = .extended, | 13049 | .tag = .extended, |
| 13004 | .data = .{ .extended = .{ | 13050 | .data = .{ .extended = .{ |
| 13005 | .opcode = .struct_decl, | 13051 | .opcode = .struct_decl, |
| 13006 | .small = @bitCast(Zir.Inst.StructDecl.Small{ | 13052 | .small = @bitCast(Zir.Inst.StructDecl.Small{ |
| 13053 | .has_captures_len = args.captures_len != 0, | ||
| 13007 | .has_fields_len = args.fields_len != 0, | 13054 | .has_fields_len = args.fields_len != 0, |
| 13008 | .has_decls_len = args.decls_len != 0, | 13055 | .has_decls_len = args.decls_len != 0, |
| 13009 | .has_backing_int = args.backing_int_ref != .none, | 13056 | .has_backing_int = args.has_backing_int, |
| 13010 | .known_non_opv = args.known_non_opv, | 13057 | .known_non_opv = args.known_non_opv, |
| 13011 | .known_comptime_only = args.known_comptime_only, | 13058 | .known_comptime_only = args.known_comptime_only, |
| 13012 | .is_tuple = args.is_tuple, | 13059 | .is_tuple = args.is_tuple, |
| ... | @@ -13024,6 +13071,7 @@ const GenZir = struct { | ... | @@ -13024,6 +13071,7 @@ const GenZir = struct { |
| 13024 | fn setUnion(gz: *GenZir, inst: Zir.Inst.Index, args: struct { | 13071 | fn setUnion(gz: *GenZir, inst: Zir.Inst.Index, args: struct { |
| 13025 | src_node: Ast.Node.Index, | 13072 | src_node: Ast.Node.Index, |
| 13026 | tag_type: Zir.Inst.Ref, | 13073 | tag_type: Zir.Inst.Ref, |
| 13074 | captures_len: u32, | ||
| 13027 | body_len: u32, | 13075 | body_len: u32, |
| 13028 | fields_len: u32, | 13076 | fields_len: u32, |
| 13029 | decls_len: u32, | 13077 | decls_len: u32, |
| ... | @@ -13039,7 +13087,7 @@ const GenZir = struct { | ... | @@ -13039,7 +13087,7 @@ const GenZir = struct { |
| 13039 | 13087 | ||
| 13040 | const fields_hash_arr: [4]u32 = @bitCast(args.fields_hash); | 13088 | const fields_hash_arr: [4]u32 = @bitCast(args.fields_hash); |
| 13041 | 13089 | ||
| 13042 | try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.UnionDecl).Struct.fields.len + 4); | 13090 | try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.UnionDecl).Struct.fields.len + 5); |
| 13043 | const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.UnionDecl{ | 13091 | const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.UnionDecl{ |
| 13044 | .fields_hash_0 = fields_hash_arr[0], | 13092 | .fields_hash_0 = fields_hash_arr[0], |
| 13045 | .fields_hash_1 = fields_hash_arr[1], | 13093 | .fields_hash_1 = fields_hash_arr[1], |
| ... | @@ -13051,6 +13099,9 @@ const GenZir = struct { | ... | @@ -13051,6 +13099,9 @@ const GenZir = struct { |
| 13051 | if (args.tag_type != .none) { | 13099 | if (args.tag_type != .none) { |
| 13052 | astgen.extra.appendAssumeCapacity(@intFromEnum(args.tag_type)); | 13100 | astgen.extra.appendAssumeCapacity(@intFromEnum(args.tag_type)); |
| 13053 | } | 13101 | } |
| 13102 | if (args.captures_len != 0) { | ||
| 13103 | astgen.extra.appendAssumeCapacity(args.captures_len); | ||
| 13104 | } | ||
| 13054 | if (args.body_len != 0) { | 13105 | if (args.body_len != 0) { |
| 13055 | astgen.extra.appendAssumeCapacity(args.body_len); | 13106 | astgen.extra.appendAssumeCapacity(args.body_len); |
| 13056 | } | 13107 | } |
| ... | @@ -13066,6 +13117,7 @@ const GenZir = struct { | ... | @@ -13066,6 +13117,7 @@ const GenZir = struct { |
| 13066 | .opcode = .union_decl, | 13117 | .opcode = .union_decl, |
| 13067 | .small = @bitCast(Zir.Inst.UnionDecl.Small{ | 13118 | .small = @bitCast(Zir.Inst.UnionDecl.Small{ |
| 13068 | .has_tag_type = args.tag_type != .none, | 13119 | .has_tag_type = args.tag_type != .none, |
| 13120 | .has_captures_len = args.captures_len != 0, | ||
| 13069 | .has_body_len = args.body_len != 0, | 13121 | .has_body_len = args.body_len != 0, |
| 13070 | .has_fields_len = args.fields_len != 0, | 13122 | .has_fields_len = args.fields_len != 0, |
| 13071 | .has_decls_len = args.decls_len != 0, | 13123 | .has_decls_len = args.decls_len != 0, |
| ... | @@ -13082,6 +13134,7 @@ const GenZir = struct { | ... | @@ -13082,6 +13134,7 @@ const GenZir = struct { |
| 13082 | fn setEnum(gz: *GenZir, inst: Zir.Inst.Index, args: struct { | 13134 | fn setEnum(gz: *GenZir, inst: Zir.Inst.Index, args: struct { |
| 13083 | src_node: Ast.Node.Index, | 13135 | src_node: Ast.Node.Index, |
| 13084 | tag_type: Zir.Inst.Ref, | 13136 | tag_type: Zir.Inst.Ref, |
| 13137 | captures_len: u32, | ||
| 13085 | body_len: u32, | 13138 | body_len: u32, |
| 13086 | fields_len: u32, | 13139 | fields_len: u32, |
| 13087 | decls_len: u32, | 13140 | decls_len: u32, |
| ... | @@ -13095,7 +13148,7 @@ const GenZir = struct { | ... | @@ -13095,7 +13148,7 @@ const GenZir = struct { |
| 13095 | 13148 | ||
| 13096 | const fields_hash_arr: [4]u32 = @bitCast(args.fields_hash); | 13149 | const fields_hash_arr: [4]u32 = @bitCast(args.fields_hash); |
| 13097 | 13150 | ||
| 13098 | try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.EnumDecl).Struct.fields.len + 4); | 13151 | try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.EnumDecl).Struct.fields.len + 5); |
| 13099 | const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.EnumDecl{ | 13152 | const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.EnumDecl{ |
| 13100 | .fields_hash_0 = fields_hash_arr[0], | 13153 | .fields_hash_0 = fields_hash_arr[0], |
| 13101 | .fields_hash_1 = fields_hash_arr[1], | 13154 | .fields_hash_1 = fields_hash_arr[1], |
| ... | @@ -13107,6 +13160,9 @@ const GenZir = struct { | ... | @@ -13107,6 +13160,9 @@ const GenZir = struct { |
| 13107 | if (args.tag_type != .none) { | 13160 | if (args.tag_type != .none) { |
| 13108 | astgen.extra.appendAssumeCapacity(@intFromEnum(args.tag_type)); | 13161 | astgen.extra.appendAssumeCapacity(@intFromEnum(args.tag_type)); |
| 13109 | } | 13162 | } |
| 13163 | if (args.captures_len != 0) { | ||
| 13164 | astgen.extra.appendAssumeCapacity(args.captures_len); | ||
| 13165 | } | ||
| 13110 | if (args.body_len != 0) { | 13166 | if (args.body_len != 0) { |
| 13111 | astgen.extra.appendAssumeCapacity(args.body_len); | 13167 | astgen.extra.appendAssumeCapacity(args.body_len); |
| 13112 | } | 13168 | } |
| ... | @@ -13122,6 +13178,7 @@ const GenZir = struct { | ... | @@ -13122,6 +13178,7 @@ const GenZir = struct { |
| 13122 | .opcode = .enum_decl, | 13178 | .opcode = .enum_decl, |
| 13123 | .small = @bitCast(Zir.Inst.EnumDecl.Small{ | 13179 | .small = @bitCast(Zir.Inst.EnumDecl.Small{ |
| 13124 | .has_tag_type = args.tag_type != .none, | 13180 | .has_tag_type = args.tag_type != .none, |
| 13181 | .has_captures_len = args.captures_len != 0, | ||
| 13125 | .has_body_len = args.body_len != 0, | 13182 | .has_body_len = args.body_len != 0, |
| 13126 | .has_fields_len = args.fields_len != 0, | 13183 | .has_fields_len = args.fields_len != 0, |
| 13127 | .has_decls_len = args.decls_len != 0, | 13184 | .has_decls_len = args.decls_len != 0, |
| ... | @@ -13135,6 +13192,7 @@ const GenZir = struct { | ... | @@ -13135,6 +13192,7 @@ const GenZir = struct { |
| 13135 | 13192 | ||
| 13136 | fn setOpaque(gz: *GenZir, inst: Zir.Inst.Index, args: struct { | 13193 | fn setOpaque(gz: *GenZir, inst: Zir.Inst.Index, args: struct { |
| 13137 | src_node: Ast.Node.Index, | 13194 | src_node: Ast.Node.Index, |
| 13195 | captures_len: u32, | ||
| 13138 | decls_len: u32, | 13196 | decls_len: u32, |
| 13139 | }) !void { | 13197 | }) !void { |
| 13140 | const astgen = gz.astgen; | 13198 | const astgen = gz.astgen; |
| ... | @@ -13142,11 +13200,14 @@ const GenZir = struct { | ... | @@ -13142,11 +13200,14 @@ const GenZir = struct { |
| 13142 | 13200 | ||
| 13143 | assert(args.src_node != 0); | 13201 | assert(args.src_node != 0); |
| 13144 | 13202 | ||
| 13145 | try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.OpaqueDecl).Struct.fields.len + 1); | 13203 | try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.OpaqueDecl).Struct.fields.len + 2); |
| 13146 | const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.OpaqueDecl{ | 13204 | const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.OpaqueDecl{ |
| 13147 | .src_node = gz.nodeIndexToRelative(args.src_node), | 13205 | .src_node = gz.nodeIndexToRelative(args.src_node), |
| 13148 | }); | 13206 | }); |
| 13149 | 13207 | ||
| 13208 | if (args.captures_len != 0) { | ||
| 13209 | astgen.extra.appendAssumeCapacity(args.captures_len); | ||
| 13210 | } | ||
| 13150 | if (args.decls_len != 0) { | 13211 | if (args.decls_len != 0) { |
| 13151 | astgen.extra.appendAssumeCapacity(args.decls_len); | 13212 | astgen.extra.appendAssumeCapacity(args.decls_len); |
| 13152 | } | 13213 | } |
| ... | @@ -13155,6 +13216,7 @@ const GenZir = struct { | ... | @@ -13155,6 +13216,7 @@ const GenZir = struct { |
| 13155 | .data = .{ .extended = .{ | 13216 | .data = .{ .extended = .{ |
| 13156 | .opcode = .opaque_decl, | 13217 | .opcode = .opaque_decl, |
| 13157 | .small = @bitCast(Zir.Inst.OpaqueDecl.Small{ | 13218 | .small = @bitCast(Zir.Inst.OpaqueDecl.Small{ |
| 13219 | .has_captures_len = args.captures_len != 0, | ||
| 13158 | .has_decls_len = args.decls_len != 0, | 13220 | .has_decls_len = args.decls_len != 0, |
| 13159 | .name_strategy = gz.anon_name_strategy, | 13221 | .name_strategy = gz.anon_name_strategy, |
| 13160 | }), | 13222 | }), |
| ... | @@ -13197,15 +13259,6 @@ const GenZir = struct { | ... | @@ -13197,15 +13259,6 @@ const GenZir = struct { |
| 13197 | } | 13259 | } |
| 13198 | } | 13260 | } |
| 13199 | 13261 | ||
| 13200 | fn addNamespaceCaptures(gz: *GenZir, namespace: *Scope.Namespace) !void { | ||
| 13201 | if (namespace.captures.count() > 0) { | ||
| 13202 | try gz.instructions.ensureUnusedCapacity(gz.astgen.gpa, namespace.captures.count()); | ||
| 13203 | for (namespace.captures.values()) |capture| { | ||
| 13204 | gz.instructions.appendAssumeCapacity(capture); | ||
| 13205 | } | ||
| 13206 | } | ||
| 13207 | } | ||
| 13208 | |||
| 13209 | fn addDbgVar(gz: *GenZir, tag: Zir.Inst.Tag, name: Zir.NullTerminatedString, inst: Zir.Inst.Ref) !void { | 13262 | fn addDbgVar(gz: *GenZir, tag: Zir.Inst.Tag, name: Zir.NullTerminatedString, inst: Zir.Inst.Ref) !void { |
| 13210 | if (gz.is_comptime) return; | 13263 | if (gz.is_comptime) return; |
| 13211 | 13264 | ||
| ... | @@ -13305,7 +13358,7 @@ fn detectLocalShadowing( | ... | @@ -13305,7 +13358,7 @@ fn detectLocalShadowing( |
| 13305 | } | 13358 | } |
| 13306 | s = local_ptr.parent; | 13359 | s = local_ptr.parent; |
| 13307 | }, | 13360 | }, |
| 13308 | .namespace, .enum_namespace => { | 13361 | .namespace => { |
| 13309 | outer_scope = true; | 13362 | outer_scope = true; |
| 13310 | const ns = s.cast(Scope.Namespace).?; | 13363 | const ns = s.cast(Scope.Namespace).?; |
| 13311 | const decl_node = ns.decls.get(ident_name) orelse { | 13364 | const decl_node = ns.decls.get(ident_name) orelse { |
| ... | @@ -13478,7 +13531,7 @@ fn scanDecls(astgen: *AstGen, namespace: *Scope.Namespace, members: []const Ast. | ... | @@ -13478,7 +13531,7 @@ fn scanDecls(astgen: *AstGen, namespace: *Scope.Namespace, members: []const Ast. |
| 13478 | } | 13531 | } |
| 13479 | s = local_ptr.parent; | 13532 | s = local_ptr.parent; |
| 13480 | }, | 13533 | }, |
| 13481 | .namespace, .enum_namespace => s = s.cast(Scope.Namespace).?.parent, | 13534 | .namespace => s = s.cast(Scope.Namespace).?.parent, |
| 13482 | .gen_zir => s = s.cast(GenZir).?.parent, | 13535 | .gen_zir => s = s.cast(GenZir).?.parent, |
| 13483 | .defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent, | 13536 | .defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent, |
| 13484 | .top => break, | 13537 | .top => break, |
lib/std/zig/Zir.zig+99-48| ... | @@ -1004,17 +1004,6 @@ pub const Inst = struct { | ... | @@ -1004,17 +1004,6 @@ pub const Inst = struct { |
| 1004 | @"resume", | 1004 | @"resume", |
| 1005 | @"await", | 1005 | @"await", |
| 1006 | 1006 | ||
| 1007 | /// When a type or function refers to a comptime value from an outer | ||
| 1008 | /// scope, that forms a closure over comptime value. The outer scope | ||
| 1009 | /// will record a capture of that value, which encodes its current state | ||
| 1010 | /// and marks it to persist. Uses `un_tok` field. Operand is the | ||
| 1011 | /// instruction value to capture. | ||
| 1012 | closure_capture, | ||
| 1013 | /// The inner scope of a closure uses closure_get to retrieve the value | ||
| 1014 | /// stored by the outer scope. Uses `inst_node` field. Operand is the | ||
| 1015 | /// closure_capture instruction ref. | ||
| 1016 | closure_get, | ||
| 1017 | |||
| 1018 | /// A defer statement. | 1007 | /// A defer statement. |
| 1019 | /// Uses the `defer` union field. | 1008 | /// Uses the `defer` union field. |
| 1020 | @"defer", | 1009 | @"defer", |
| ... | @@ -1251,8 +1240,6 @@ pub const Inst = struct { | ... | @@ -1251,8 +1240,6 @@ pub const Inst = struct { |
| 1251 | .@"await", | 1240 | .@"await", |
| 1252 | .ret_err_value_code, | 1241 | .ret_err_value_code, |
| 1253 | .extended, | 1242 | .extended, |
| 1254 | .closure_get, | ||
| 1255 | .closure_capture, | ||
| 1256 | .ret_ptr, | 1243 | .ret_ptr, |
| 1257 | .ret_type, | 1244 | .ret_type, |
| 1258 | .@"try", | 1245 | .@"try", |
| ... | @@ -1542,8 +1529,6 @@ pub const Inst = struct { | ... | @@ -1542,8 +1529,6 @@ pub const Inst = struct { |
| 1542 | .@"resume", | 1529 | .@"resume", |
| 1543 | .@"await", | 1530 | .@"await", |
| 1544 | .ret_err_value_code, | 1531 | .ret_err_value_code, |
| 1545 | .closure_get, | ||
| 1546 | .closure_capture, | ||
| 1547 | .@"break", | 1532 | .@"break", |
| 1548 | .break_inline, | 1533 | .break_inline, |
| 1549 | .condbr, | 1534 | .condbr, |
| ... | @@ -1829,9 +1814,6 @@ pub const Inst = struct { | ... | @@ -1829,9 +1814,6 @@ pub const Inst = struct { |
| 1829 | .@"resume" = .un_node, | 1814 | .@"resume" = .un_node, |
| 1830 | .@"await" = .un_node, | 1815 | .@"await" = .un_node, |
| 1831 | 1816 | ||
| 1832 | .closure_capture = .un_tok, | ||
| 1833 | .closure_get = .inst_node, | ||
| 1834 | |||
| 1835 | .@"defer" = .@"defer", | 1817 | .@"defer" = .@"defer", |
| 1836 | .defer_err_code = .defer_err_code, | 1818 | .defer_err_code = .defer_err_code, |
| 1837 | 1819 | ||
| ... | @@ -2074,6 +2056,10 @@ pub const Inst = struct { | ... | @@ -2074,6 +2056,10 @@ pub const Inst = struct { |
| 2074 | /// `operand` is payload index to `RestoreErrRetIndex`. | 2056 | /// `operand` is payload index to `RestoreErrRetIndex`. |
| 2075 | /// `small` is undefined. | 2057 | /// `small` is undefined. |
| 2076 | restore_err_ret_index, | 2058 | restore_err_ret_index, |
| 2059 | /// Retrieves a value from the current type declaration scope's closure. | ||
| 2060 | /// `operand` is `src_node: i32`. | ||
| 2061 | /// `small` is closure index. | ||
| 2062 | closure_get, | ||
| 2077 | /// Used as a placeholder instruction which is just a dummy index for Sema to replace | 2063 | /// Used as a placeholder instruction which is just a dummy index for Sema to replace |
| 2078 | /// with a specific value. For instance, this is used for the capture of an `errdefer`. | 2064 | /// with a specific value. For instance, this is used for the capture of an `errdefer`. |
| 2079 | /// This should never appear in a body. | 2065 | /// This should never appear in a body. |
| ... | @@ -2949,7 +2935,7 @@ pub const Inst = struct { | ... | @@ -2949,7 +2935,7 @@ pub const Inst = struct { |
| 2949 | /// These are stored in trailing data in `extra` for each prong. | 2935 | /// These are stored in trailing data in `extra` for each prong. |
| 2950 | pub const ProngInfo = packed struct(u32) { | 2936 | pub const ProngInfo = packed struct(u32) { |
| 2951 | body_len: u28, | 2937 | body_len: u28, |
| 2952 | capture: Capture, | 2938 | capture: ProngInfo.Capture, |
| 2953 | is_inline: bool, | 2939 | is_inline: bool, |
| 2954 | has_tag_capture: bool, | 2940 | has_tag_capture: bool, |
| 2955 | 2941 | ||
| ... | @@ -3013,19 +2999,21 @@ pub const Inst = struct { | ... | @@ -3013,19 +2999,21 @@ pub const Inst = struct { |
| 3013 | }; | 2999 | }; |
| 3014 | 3000 | ||
| 3015 | /// Trailing: | 3001 | /// Trailing: |
| 3016 | /// 0. fields_len: u32, // if has_fields_len | 3002 | /// 0. captures_len: u32 // if has_captures_len |
| 3017 | /// 1. decls_len: u32, // if has_decls_len | 3003 | /// 1. fields_len: u32, // if has_fields_len |
| 3018 | /// 2. backing_int_body_len: u32, // if has_backing_int | 3004 | /// 2. decls_len: u32, // if has_decls_len |
| 3019 | /// 3. backing_int_ref: Ref, // if has_backing_int and backing_int_body_len is 0 | 3005 | /// 3. capture: Capture // for every captures_len |
| 3020 | /// 4. backing_int_body_inst: Inst, // if has_backing_int and backing_int_body_len is > 0 | 3006 | /// 4. backing_int_body_len: u32, // if has_backing_int |
| 3021 | /// 5. decl: Index, // for every decls_len; points to a `declaration` instruction | 3007 | /// 5. backing_int_ref: Ref, // if has_backing_int and backing_int_body_len is 0 |
| 3022 | /// 6. flags: u32 // for every 8 fields | 3008 | /// 6. backing_int_body_inst: Inst, // if has_backing_int and backing_int_body_len is > 0 |
| 3009 | /// 7. decl: Index, // for every decls_len; points to a `declaration` instruction | ||
| 3010 | /// 8. flags: u32 // for every 8 fields | ||
| 3023 | /// - sets of 4 bits: | 3011 | /// - sets of 4 bits: |
| 3024 | /// 0b000X: whether corresponding field has an align expression | 3012 | /// 0b000X: whether corresponding field has an align expression |
| 3025 | /// 0b00X0: whether corresponding field has a default expression | 3013 | /// 0b00X0: whether corresponding field has a default expression |
| 3026 | /// 0b0X00: whether corresponding field is comptime | 3014 | /// 0b0X00: whether corresponding field is comptime |
| 3027 | /// 0bX000: whether corresponding field has a type expression | 3015 | /// 0bX000: whether corresponding field has a type expression |
| 3028 | /// 7. fields: { // for every fields_len | 3016 | /// 9. fields: { // for every fields_len |
| 3029 | /// field_name: u32, // if !is_tuple | 3017 | /// field_name: u32, // if !is_tuple |
| 3030 | /// doc_comment: NullTerminatedString, // .empty if no doc comment | 3018 | /// doc_comment: NullTerminatedString, // .empty if no doc comment |
| 3031 | /// field_type: Ref, // if corresponding bit is not set. none means anytype. | 3019 | /// field_type: Ref, // if corresponding bit is not set. none means anytype. |
| ... | @@ -3033,7 +3021,7 @@ pub const Inst = struct { | ... | @@ -3033,7 +3021,7 @@ pub const Inst = struct { |
| 3033 | /// align_body_len: u32, // if corresponding bit is set | 3021 | /// align_body_len: u32, // if corresponding bit is set |
| 3034 | /// init_body_len: u32, // if corresponding bit is set | 3022 | /// init_body_len: u32, // if corresponding bit is set |
| 3035 | /// } | 3023 | /// } |
| 3036 | /// 8. bodies: { // for every fields_len | 3024 | /// 10. bodies: { // for every fields_len |
| 3037 | /// field_type_body_inst: Inst, // for each field_type_body_len | 3025 | /// field_type_body_inst: Inst, // for each field_type_body_len |
| 3038 | /// align_body_inst: Inst, // for each align_body_len | 3026 | /// align_body_inst: Inst, // for each align_body_len |
| 3039 | /// init_body_inst: Inst, // for each init_body_len | 3027 | /// init_body_inst: Inst, // for each init_body_len |
| ... | @@ -3052,6 +3040,7 @@ pub const Inst = struct { | ... | @@ -3052,6 +3040,7 @@ pub const Inst = struct { |
| 3052 | } | 3040 | } |
| 3053 | 3041 | ||
| 3054 | pub const Small = packed struct { | 3042 | pub const Small = packed struct { |
| 3043 | has_captures_len: bool, | ||
| 3055 | has_fields_len: bool, | 3044 | has_fields_len: bool, |
| 3056 | has_decls_len: bool, | 3045 | has_decls_len: bool, |
| 3057 | has_backing_int: bool, | 3046 | has_backing_int: bool, |
| ... | @@ -3063,10 +3052,35 @@ pub const Inst = struct { | ... | @@ -3063,10 +3052,35 @@ pub const Inst = struct { |
| 3063 | any_default_inits: bool, | 3052 | any_default_inits: bool, |
| 3064 | any_comptime_fields: bool, | 3053 | any_comptime_fields: bool, |
| 3065 | any_aligned_fields: bool, | 3054 | any_aligned_fields: bool, |
| 3066 | _: u3 = undefined, | 3055 | _: u2 = undefined, |
| 3067 | }; | 3056 | }; |
| 3068 | }; | 3057 | }; |
| 3069 | 3058 | ||
| 3059 | /// Represents a single value being captured in a type declaration's closure. | ||
| 3060 | /// If high bit is 0, this represents a `Zir.Inst,Index`. | ||
| 3061 | /// If high bit is 1, this represents an index into the last closure. | ||
| 3062 | pub const Capture = enum(u32) { | ||
| 3063 | _, | ||
| 3064 | pub const Unwrapped = union(enum) { | ||
| 3065 | inst: Zir.Inst.Index, | ||
| 3066 | nested: u16, | ||
| 3067 | }; | ||
| 3068 | pub fn wrap(cap: Unwrapped) Capture { | ||
| 3069 | return switch (cap) { | ||
| 3070 | .inst => |inst| @enumFromInt(@intFromEnum(inst)), | ||
| 3071 | .nested => |idx| @enumFromInt((1 << 31) | @as(u32, idx)), | ||
| 3072 | }; | ||
| 3073 | } | ||
| 3074 | pub fn unwrap(cap: Capture) Unwrapped { | ||
| 3075 | const raw = @intFromEnum(cap); | ||
| 3076 | const tag: u1 = @intCast(raw >> 31); | ||
| 3077 | return switch (tag) { | ||
| 3078 | 0 => .{ .inst = @enumFromInt(raw) }, | ||
| 3079 | 1 => .{ .nested = @truncate(raw) }, | ||
| 3080 | }; | ||
| 3081 | } | ||
| 3082 | }; | ||
| 3083 | |||
| 3070 | pub const NameStrategy = enum(u2) { | 3084 | pub const NameStrategy = enum(u2) { |
| 3071 | /// Use the same name as the parent declaration name. | 3085 | /// Use the same name as the parent declaration name. |
| 3072 | /// e.g. `const Foo = struct {...};`. | 3086 | /// e.g. `const Foo = struct {...};`. |
| ... | @@ -3098,14 +3112,16 @@ pub const Inst = struct { | ... | @@ -3098,14 +3112,16 @@ pub const Inst = struct { |
| 3098 | 3112 | ||
| 3099 | /// Trailing: | 3113 | /// Trailing: |
| 3100 | /// 0. tag_type: Ref, // if has_tag_type | 3114 | /// 0. tag_type: Ref, // if has_tag_type |
| 3101 | /// 1. body_len: u32, // if has_body_len | 3115 | /// 1. captures_len: u32, // if has_captures_len |
| 3102 | /// 2. fields_len: u32, // if has_fields_len | 3116 | /// 2. body_len: u32, // if has_body_len |
| 3103 | /// 3. decls_len: u32, // if has_decls_len | 3117 | /// 3. fields_len: u32, // if has_fields_len |
| 3104 | /// 4. decl: Index, // for every decls_len; points to a `declaration` instruction | 3118 | /// 4. decls_len: u32, // if has_decls_len |
| 3105 | /// 5. inst: Index // for every body_len | 3119 | /// 5. capture: Capture // for every captures_len |
| 3106 | /// 6. has_bits: u32 // for every 32 fields | 3120 | /// 6. decl: Index, // for every decls_len; points to a `declaration` instruction |
| 3121 | /// 7. inst: Index // for every body_len | ||
| 3122 | /// 8. has_bits: u32 // for every 32 fields | ||
| 3107 | /// - the bit is whether corresponding field has an value expression | 3123 | /// - the bit is whether corresponding field has an value expression |
| 3108 | /// 7. fields: { // for every fields_len | 3124 | /// 9. fields: { // for every fields_len |
| 3109 | /// field_name: u32, | 3125 | /// field_name: u32, |
| 3110 | /// doc_comment: u32, // .empty if no doc_comment | 3126 | /// doc_comment: u32, // .empty if no doc_comment |
| 3111 | /// value: Ref, // if corresponding bit is set | 3127 | /// value: Ref, // if corresponding bit is set |
| ... | @@ -3125,29 +3141,32 @@ pub const Inst = struct { | ... | @@ -3125,29 +3141,32 @@ pub const Inst = struct { |
| 3125 | 3141 | ||
| 3126 | pub const Small = packed struct { | 3142 | pub const Small = packed struct { |
| 3127 | has_tag_type: bool, | 3143 | has_tag_type: bool, |
| 3144 | has_captures_len: bool, | ||
| 3128 | has_body_len: bool, | 3145 | has_body_len: bool, |
| 3129 | has_fields_len: bool, | 3146 | has_fields_len: bool, |
| 3130 | has_decls_len: bool, | 3147 | has_decls_len: bool, |
| 3131 | name_strategy: NameStrategy, | 3148 | name_strategy: NameStrategy, |
| 3132 | nonexhaustive: bool, | 3149 | nonexhaustive: bool, |
| 3133 | _: u9 = undefined, | 3150 | _: u8 = undefined, |
| 3134 | }; | 3151 | }; |
| 3135 | }; | 3152 | }; |
| 3136 | 3153 | ||
| 3137 | /// Trailing: | 3154 | /// Trailing: |
| 3138 | /// 0. tag_type: Ref, // if has_tag_type | 3155 | /// 0. tag_type: Ref, // if has_tag_type |
| 3139 | /// 1. body_len: u32, // if has_body_len | 3156 | /// 1. captures_len: u32 // if has_captures_len |
| 3140 | /// 2. fields_len: u32, // if has_fields_len | 3157 | /// 2. body_len: u32, // if has_body_len |
| 3141 | /// 3. decls_len: u32, // if has_decls_len | 3158 | /// 3. fields_len: u32, // if has_fields_len |
| 3142 | /// 4. decl: Index, // for every decls_len; points to a `declaration` instruction | 3159 | /// 4. decls_len: u37, // if has_decls_len |
| 3143 | /// 5. inst: Index // for every body_len | 3160 | /// 5. capture: Capture // for every captures_len |
| 3144 | /// 6. has_bits: u32 // for every 8 fields | 3161 | /// 6. decl: Index, // for every decls_len; points to a `declaration` instruction |
| 3162 | /// 7. inst: Index // for every body_len | ||
| 3163 | /// 8. has_bits: u32 // for every 8 fields | ||
| 3145 | /// - sets of 4 bits: | 3164 | /// - sets of 4 bits: |
| 3146 | /// 0b000X: whether corresponding field has a type expression | 3165 | /// 0b000X: whether corresponding field has a type expression |
| 3147 | /// 0b00X0: whether corresponding field has a align expression | 3166 | /// 0b00X0: whether corresponding field has a align expression |
| 3148 | /// 0b0X00: whether corresponding field has a tag value expression | 3167 | /// 0b0X00: whether corresponding field has a tag value expression |
| 3149 | /// 0bX000: unused | 3168 | /// 0bX000: unused |
| 3150 | /// 7. fields: { // for every fields_len | 3169 | /// 9. fields: { // for every fields_len |
| 3151 | /// field_name: NullTerminatedString, // null terminated string index | 3170 | /// field_name: NullTerminatedString, // null terminated string index |
| 3152 | /// doc_comment: NullTerminatedString, // .empty if no doc comment | 3171 | /// doc_comment: NullTerminatedString, // .empty if no doc comment |
| 3153 | /// field_type: Ref, // if corresponding bit is set | 3172 | /// field_type: Ref, // if corresponding bit is set |
| ... | @@ -3170,6 +3189,7 @@ pub const Inst = struct { | ... | @@ -3170,6 +3189,7 @@ pub const Inst = struct { |
| 3170 | 3189 | ||
| 3171 | pub const Small = packed struct { | 3190 | pub const Small = packed struct { |
| 3172 | has_tag_type: bool, | 3191 | has_tag_type: bool, |
| 3192 | has_captures_len: bool, | ||
| 3173 | has_body_len: bool, | 3193 | has_body_len: bool, |
| 3174 | has_fields_len: bool, | 3194 | has_fields_len: bool, |
| 3175 | has_decls_len: bool, | 3195 | has_decls_len: bool, |
| ... | @@ -3183,13 +3203,15 @@ pub const Inst = struct { | ... | @@ -3183,13 +3203,15 @@ pub const Inst = struct { |
| 3183 | /// true | false | union(T) { } | 3203 | /// true | false | union(T) { } |
| 3184 | auto_enum_tag: bool, | 3204 | auto_enum_tag: bool, |
| 3185 | any_aligned_fields: bool, | 3205 | any_aligned_fields: bool, |
| 3186 | _: u6 = undefined, | 3206 | _: u5 = undefined, |
| 3187 | }; | 3207 | }; |
| 3188 | }; | 3208 | }; |
| 3189 | 3209 | ||
| 3190 | /// Trailing: | 3210 | /// Trailing: |
| 3191 | /// 0. decls_len: u32, // if has_decls_len | 3211 | /// 0. captures_len: u32, // if has_captures_len |
| 3192 | /// 1. decl: Index, // for every decls_len; points to a `declaration` instruction | 3212 | /// 1. decls_len: u32, // if has_decls_len |
| 3213 | /// 2. capture: Capture, // for every captures_len | ||
| 3214 | /// 3. decl: Index, // for every decls_len; points to a `declaration` instruction | ||
| 3193 | pub const OpaqueDecl = struct { | 3215 | pub const OpaqueDecl = struct { |
| 3194 | src_node: i32, | 3216 | src_node: i32, |
| 3195 | 3217 | ||
| ... | @@ -3198,9 +3220,10 @@ pub const Inst = struct { | ... | @@ -3198,9 +3220,10 @@ pub const Inst = struct { |
| 3198 | } | 3220 | } |
| 3199 | 3221 | ||
| 3200 | pub const Small = packed struct { | 3222 | pub const Small = packed struct { |
| 3223 | has_captures_len: bool, | ||
| 3201 | has_decls_len: bool, | 3224 | has_decls_len: bool, |
| 3202 | name_strategy: NameStrategy, | 3225 | name_strategy: NameStrategy, |
| 3203 | _: u13 = undefined, | 3226 | _: u12 = undefined, |
| 3204 | }; | 3227 | }; |
| 3205 | }; | 3228 | }; |
| 3206 | 3229 | ||
| ... | @@ -3502,6 +3525,11 @@ pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator { | ... | @@ -3502,6 +3525,11 @@ pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator { |
| 3502 | .struct_decl => { | 3525 | .struct_decl => { |
| 3503 | const small: Inst.StructDecl.Small = @bitCast(extended.small); | 3526 | const small: Inst.StructDecl.Small = @bitCast(extended.small); |
| 3504 | var extra_index: u32 = @intCast(extended.operand + @typeInfo(Inst.StructDecl).Struct.fields.len); | 3527 | var extra_index: u32 = @intCast(extended.operand + @typeInfo(Inst.StructDecl).Struct.fields.len); |
| 3528 | const captures_len = if (small.has_captures_len) captures_len: { | ||
| 3529 | const captures_len = zir.extra[extra_index]; | ||
| 3530 | extra_index += 1; | ||
| 3531 | break :captures_len captures_len; | ||
| 3532 | } else 0; | ||
| 3505 | extra_index += @intFromBool(small.has_fields_len); | 3533 | extra_index += @intFromBool(small.has_fields_len); |
| 3506 | const decls_len = if (small.has_decls_len) decls_len: { | 3534 | const decls_len = if (small.has_decls_len) decls_len: { |
| 3507 | const decls_len = zir.extra[extra_index]; | 3535 | const decls_len = zir.extra[extra_index]; |
| ... | @@ -3509,6 +3537,8 @@ pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator { | ... | @@ -3509,6 +3537,8 @@ pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator { |
| 3509 | break :decls_len decls_len; | 3537 | break :decls_len decls_len; |
| 3510 | } else 0; | 3538 | } else 0; |
| 3511 | 3539 | ||
| 3540 | extra_index += captures_len; | ||
| 3541 | |||
| 3512 | if (small.has_backing_int) { | 3542 | if (small.has_backing_int) { |
| 3513 | const backing_int_body_len = zir.extra[extra_index]; | 3543 | const backing_int_body_len = zir.extra[extra_index]; |
| 3514 | extra_index += 1; // backing_int_body_len | 3544 | extra_index += 1; // backing_int_body_len |
| ... | @@ -3529,6 +3559,11 @@ pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator { | ... | @@ -3529,6 +3559,11 @@ pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator { |
| 3529 | const small: Inst.EnumDecl.Small = @bitCast(extended.small); | 3559 | const small: Inst.EnumDecl.Small = @bitCast(extended.small); |
| 3530 | var extra_index: u32 = @intCast(extended.operand + @typeInfo(Inst.EnumDecl).Struct.fields.len); | 3560 | var extra_index: u32 = @intCast(extended.operand + @typeInfo(Inst.EnumDecl).Struct.fields.len); |
| 3531 | extra_index += @intFromBool(small.has_tag_type); | 3561 | extra_index += @intFromBool(small.has_tag_type); |
| 3562 | const captures_len = if (small.has_captures_len) captures_len: { | ||
| 3563 | const captures_len = zir.extra[extra_index]; | ||
| 3564 | extra_index += 1; | ||
| 3565 | break :captures_len captures_len; | ||
| 3566 | } else 0; | ||
| 3532 | extra_index += @intFromBool(small.has_body_len); | 3567 | extra_index += @intFromBool(small.has_body_len); |
| 3533 | extra_index += @intFromBool(small.has_fields_len); | 3568 | extra_index += @intFromBool(small.has_fields_len); |
| 3534 | const decls_len = if (small.has_decls_len) decls_len: { | 3569 | const decls_len = if (small.has_decls_len) decls_len: { |
| ... | @@ -3537,6 +3572,8 @@ pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator { | ... | @@ -3537,6 +3572,8 @@ pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator { |
| 3537 | break :decls_len decls_len; | 3572 | break :decls_len decls_len; |
| 3538 | } else 0; | 3573 | } else 0; |
| 3539 | 3574 | ||
| 3575 | extra_index += captures_len; | ||
| 3576 | |||
| 3540 | return .{ | 3577 | return .{ |
| 3541 | .extra_index = extra_index, | 3578 | .extra_index = extra_index, |
| 3542 | .decls_remaining = decls_len, | 3579 | .decls_remaining = decls_len, |
| ... | @@ -3547,6 +3584,11 @@ pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator { | ... | @@ -3547,6 +3584,11 @@ pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator { |
| 3547 | const small: Inst.UnionDecl.Small = @bitCast(extended.small); | 3584 | const small: Inst.UnionDecl.Small = @bitCast(extended.small); |
| 3548 | var extra_index: u32 = @intCast(extended.operand + @typeInfo(Inst.UnionDecl).Struct.fields.len); | 3585 | var extra_index: u32 = @intCast(extended.operand + @typeInfo(Inst.UnionDecl).Struct.fields.len); |
| 3549 | extra_index += @intFromBool(small.has_tag_type); | 3586 | extra_index += @intFromBool(small.has_tag_type); |
| 3587 | const captures_len = if (small.has_captures_len) captures_len: { | ||
| 3588 | const captures_len = zir.extra[extra_index]; | ||
| 3589 | extra_index += 1; | ||
| 3590 | break :captures_len captures_len; | ||
| 3591 | } else 0; | ||
| 3550 | extra_index += @intFromBool(small.has_body_len); | 3592 | extra_index += @intFromBool(small.has_body_len); |
| 3551 | extra_index += @intFromBool(small.has_fields_len); | 3593 | extra_index += @intFromBool(small.has_fields_len); |
| 3552 | const decls_len = if (small.has_decls_len) decls_len: { | 3594 | const decls_len = if (small.has_decls_len) decls_len: { |
| ... | @@ -3555,6 +3597,8 @@ pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator { | ... | @@ -3555,6 +3597,8 @@ pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator { |
| 3555 | break :decls_len decls_len; | 3597 | break :decls_len decls_len; |
| 3556 | } else 0; | 3598 | } else 0; |
| 3557 | 3599 | ||
| 3600 | extra_index += captures_len; | ||
| 3601 | |||
| 3558 | return .{ | 3602 | return .{ |
| 3559 | .extra_index = extra_index, | 3603 | .extra_index = extra_index, |
| 3560 | .decls_remaining = decls_len, | 3604 | .decls_remaining = decls_len, |
| ... | @@ -3569,6 +3613,13 @@ pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator { | ... | @@ -3569,6 +3613,13 @@ pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator { |
| 3569 | extra_index += 1; | 3613 | extra_index += 1; |
| 3570 | break :decls_len decls_len; | 3614 | break :decls_len decls_len; |
| 3571 | } else 0; | 3615 | } else 0; |
| 3616 | const captures_len = if (small.has_captures_len) captures_len: { | ||
| 3617 | const captures_len = zir.extra[extra_index]; | ||
| 3618 | extra_index += 1; | ||
| 3619 | break :captures_len captures_len; | ||
| 3620 | } else 0; | ||
| 3621 | |||
| 3622 | extra_index += captures_len; | ||
| 3572 | 3623 | ||
| 3573 | return .{ | 3624 | return .{ |
| 3574 | .extra_index = extra_index, | 3625 | .extra_index = extra_index, |
src/Autodoc.zig+56-24| ... | @@ -450,7 +450,7 @@ const Scope = struct { | ... | @@ -450,7 +450,7 @@ const Scope = struct { |
| 450 | Zir.NullTerminatedString, // index into the current file's string table (decl name) | 450 | Zir.NullTerminatedString, // index into the current file's string table (decl name) |
| 451 | *DeclStatus, | 451 | *DeclStatus, |
| 452 | ) = .{}, | 452 | ) = .{}, |
| 453 | 453 | captures: []const Zir.Inst.Capture = &.{}, | |
| 454 | enclosing_type: ?usize, // index into `types`, null = file top-level struct | 454 | enclosing_type: ?usize, // index into `types`, null = file top-level struct |
| 455 | 455 | ||
| 456 | pub const DeclStatus = union(enum) { | 456 | pub const DeclStatus = union(enum) { |
| ... | @@ -459,6 +459,14 @@ const Scope = struct { | ... | @@ -459,6 +459,14 @@ const Scope = struct { |
| 459 | NotRequested: u32, // instr_index | 459 | NotRequested: u32, // instr_index |
| 460 | }; | 460 | }; |
| 461 | 461 | ||
| 462 | fn getCapture(scope: Scope, idx: u16) struct { Zir.Inst.Index, *Scope } { | ||
| 463 | const parent = scope.parent.?; | ||
| 464 | return switch (scope.captures[idx].unwrap()) { | ||
| 465 | .inst => |inst| .{ inst, parent }, | ||
| 466 | .nested => |parent_idx| parent.getCapture(parent_idx), | ||
| 467 | }; | ||
| 468 | } | ||
| 469 | |||
| 462 | /// Returns a pointer so that the caller has a chance to modify the value | 470 | /// Returns a pointer so that the caller has a chance to modify the value |
| 463 | /// in case they decide to start analyzing a previously not requested decl. | 471 | /// in case they decide to start analyzing a previously not requested decl. |
| 464 | /// Another reason is that in some places we use the pointer to uniquely | 472 | /// Another reason is that in some places we use the pointer to uniquely |
| ... | @@ -1151,29 +1159,6 @@ fn walkInstruction( | ... | @@ -1151,29 +1159,6 @@ fn walkInstruction( |
| 1151 | .expr = .{ .comptimeExpr = 0 }, | 1159 | .expr = .{ .comptimeExpr = 0 }, |
| 1152 | }; | 1160 | }; |
| 1153 | }, | 1161 | }, |
| 1154 | .closure_get => { | ||
| 1155 | const inst_node = data[@intFromEnum(inst)].inst_node; | ||
| 1156 | |||
| 1157 | const code = try self.getBlockSource(file, parent_src, inst_node.src_node); | ||
| 1158 | const idx = self.comptime_exprs.items.len; | ||
| 1159 | try self.exprs.append(self.arena, .{ .comptimeExpr = idx }); | ||
| 1160 | try self.comptime_exprs.append(self.arena, .{ .code = code }); | ||
| 1161 | |||
| 1162 | return DocData.WalkResult{ | ||
| 1163 | .expr = .{ .comptimeExpr = idx }, | ||
| 1164 | }; | ||
| 1165 | }, | ||
| 1166 | .closure_capture => { | ||
| 1167 | const un_tok = data[@intFromEnum(inst)].un_tok; | ||
| 1168 | return try self.walkRef( | ||
| 1169 | file, | ||
| 1170 | parent_scope, | ||
| 1171 | parent_src, | ||
| 1172 | un_tok.operand, | ||
| 1173 | need_type, | ||
| 1174 | call_ctx, | ||
| 1175 | ); | ||
| 1176 | }, | ||
| 1177 | .str => { | 1162 | .str => { |
| 1178 | const str = data[@intFromEnum(inst)].str.get(file.zir); | 1163 | const str = data[@intFromEnum(inst)].str.get(file.zir); |
| 1179 | 1164 | ||
| ... | @@ -3395,11 +3380,23 @@ fn walkInstruction( | ... | @@ -3395,11 +3380,23 @@ fn walkInstruction( |
| 3395 | .enclosing_type = type_slot_index, | 3380 | .enclosing_type = type_slot_index, |
| 3396 | }; | 3381 | }; |
| 3397 | 3382 | ||
| 3383 | const small: Zir.Inst.OpaqueDecl.Small = @bitCast(extended.small); | ||
| 3398 | const extra = file.zir.extraData(Zir.Inst.OpaqueDecl, extended.operand); | 3384 | const extra = file.zir.extraData(Zir.Inst.OpaqueDecl, extended.operand); |
| 3399 | var extra_index: usize = extra.end; | 3385 | var extra_index: usize = extra.end; |
| 3400 | 3386 | ||
| 3401 | const src_info = try self.srcLocInfo(file, extra.data.src_node, parent_src); | 3387 | const src_info = try self.srcLocInfo(file, extra.data.src_node, parent_src); |
| 3402 | 3388 | ||
| 3389 | const captures_len = if (small.has_captures_len) blk: { | ||
| 3390 | const captures_len = file.zir.extra[extra_index]; | ||
| 3391 | extra_index += 1; | ||
| 3392 | break :blk captures_len; | ||
| 3393 | } else 0; | ||
| 3394 | |||
| 3395 | if (small.has_decls_len) extra_index += 1; | ||
| 3396 | |||
| 3397 | scope.captures = @ptrCast(file.zir.extra[extra_index..][0..captures_len]); | ||
| 3398 | extra_index += captures_len; | ||
| 3399 | |||
| 3403 | var decl_indexes: std.ArrayListUnmanaged(usize) = .{}; | 3400 | var decl_indexes: std.ArrayListUnmanaged(usize) = .{}; |
| 3404 | var priv_decl_indexes: std.ArrayListUnmanaged(usize) = .{}; | 3401 | var priv_decl_indexes: std.ArrayListUnmanaged(usize) = .{}; |
| 3405 | 3402 | ||
| ... | @@ -3503,6 +3500,12 @@ fn walkInstruction( | ... | @@ -3503,6 +3500,12 @@ fn walkInstruction( |
| 3503 | break :blk tag_ref; | 3500 | break :blk tag_ref; |
| 3504 | } else null; | 3501 | } else null; |
| 3505 | 3502 | ||
| 3503 | const captures_len = if (small.has_captures_len) blk: { | ||
| 3504 | const captures_len = file.zir.extra[extra_index]; | ||
| 3505 | extra_index += 1; | ||
| 3506 | break :blk captures_len; | ||
| 3507 | } else 0; | ||
| 3508 | |||
| 3506 | const body_len = if (small.has_body_len) blk: { | 3509 | const body_len = if (small.has_body_len) blk: { |
| 3507 | const body_len = file.zir.extra[extra_index]; | 3510 | const body_len = file.zir.extra[extra_index]; |
| 3508 | extra_index += 1; | 3511 | extra_index += 1; |
| ... | @@ -3520,6 +3523,11 @@ fn walkInstruction( | ... | @@ -3520,6 +3523,11 @@ fn walkInstruction( |
| 3520 | else => .{ .enumLiteral = @tagName(small.layout) }, | 3523 | else => .{ .enumLiteral = @tagName(small.layout) }, |
| 3521 | }; | 3524 | }; |
| 3522 | 3525 | ||
| 3526 | if (small.has_decls_len) extra_index += 1; | ||
| 3527 | |||
| 3528 | scope.captures = @ptrCast(file.zir.extra[extra_index..][0..captures_len]); | ||
| 3529 | extra_index += captures_len; | ||
| 3530 | |||
| 3523 | var decl_indexes: std.ArrayListUnmanaged(usize) = .{}; | 3531 | var decl_indexes: std.ArrayListUnmanaged(usize) = .{}; |
| 3524 | var priv_decl_indexes: std.ArrayListUnmanaged(usize) = .{}; | 3532 | var priv_decl_indexes: std.ArrayListUnmanaged(usize) = .{}; |
| 3525 | 3533 | ||
| ... | @@ -3631,6 +3639,12 @@ fn walkInstruction( | ... | @@ -3631,6 +3639,12 @@ fn walkInstruction( |
| 3631 | break :blk wr.expr; | 3639 | break :blk wr.expr; |
| 3632 | } else null; | 3640 | } else null; |
| 3633 | 3641 | ||
| 3642 | const captures_len = if (small.has_captures_len) blk: { | ||
| 3643 | const captures_len = file.zir.extra[extra_index]; | ||
| 3644 | extra_index += 1; | ||
| 3645 | break :blk captures_len; | ||
| 3646 | } else 0; | ||
| 3647 | |||
| 3634 | const body_len = if (small.has_body_len) blk: { | 3648 | const body_len = if (small.has_body_len) blk: { |
| 3635 | const body_len = file.zir.extra[extra_index]; | 3649 | const body_len = file.zir.extra[extra_index]; |
| 3636 | extra_index += 1; | 3650 | extra_index += 1; |
| ... | @@ -3643,6 +3657,11 @@ fn walkInstruction( | ... | @@ -3643,6 +3657,11 @@ fn walkInstruction( |
| 3643 | break :blk fields_len; | 3657 | break :blk fields_len; |
| 3644 | } else 0; | 3658 | } else 0; |
| 3645 | 3659 | ||
| 3660 | if (small.has_decls_len) extra_index += 1; | ||
| 3661 | |||
| 3662 | scope.captures = @ptrCast(file.zir.extra[extra_index..][0..captures_len]); | ||
| 3663 | extra_index += captures_len; | ||
| 3664 | |||
| 3646 | var decl_indexes: std.ArrayListUnmanaged(usize) = .{}; | 3665 | var decl_indexes: std.ArrayListUnmanaged(usize) = .{}; |
| 3647 | var priv_decl_indexes: std.ArrayListUnmanaged(usize) = .{}; | 3666 | var priv_decl_indexes: std.ArrayListUnmanaged(usize) = .{}; |
| 3648 | 3667 | ||
| ... | @@ -3759,6 +3778,12 @@ fn walkInstruction( | ... | @@ -3759,6 +3778,12 @@ fn walkInstruction( |
| 3759 | 3778 | ||
| 3760 | const src_info = try self.srcLocInfo(file, extra.data.src_node, parent_src); | 3779 | const src_info = try self.srcLocInfo(file, extra.data.src_node, parent_src); |
| 3761 | 3780 | ||
| 3781 | const captures_len = if (small.has_captures_len) blk: { | ||
| 3782 | const captures_len = file.zir.extra[extra_index]; | ||
| 3783 | extra_index += 1; | ||
| 3784 | break :blk captures_len; | ||
| 3785 | } else 0; | ||
| 3786 | |||
| 3762 | const fields_len = if (small.has_fields_len) blk: { | 3787 | const fields_len = if (small.has_fields_len) blk: { |
| 3763 | const fields_len = file.zir.extra[extra_index]; | 3788 | const fields_len = file.zir.extra[extra_index]; |
| 3764 | extra_index += 1; | 3789 | extra_index += 1; |
| ... | @@ -3768,6 +3793,9 @@ fn walkInstruction( | ... | @@ -3768,6 +3793,9 @@ fn walkInstruction( |
| 3768 | // We don't care about decls yet | 3793 | // We don't care about decls yet |
| 3769 | if (small.has_decls_len) extra_index += 1; | 3794 | if (small.has_decls_len) extra_index += 1; |
| 3770 | 3795 | ||
| 3796 | scope.captures = @ptrCast(file.zir.extra[extra_index..][0..captures_len]); | ||
| 3797 | extra_index += captures_len; | ||
| 3798 | |||
| 3771 | var backing_int: ?DocData.Expr = null; | 3799 | var backing_int: ?DocData.Expr = null; |
| 3772 | if (small.has_backing_int) { | 3800 | if (small.has_backing_int) { |
| 3773 | const backing_int_body_len = file.zir.extra[extra_index]; | 3801 | const backing_int_body_len = file.zir.extra[extra_index]; |
| ... | @@ -4018,6 +4046,10 @@ fn walkInstruction( | ... | @@ -4018,6 +4046,10 @@ fn walkInstruction( |
| 4018 | .expr = .{ .cmpxchgIndex = cmpxchg_index }, | 4046 | .expr = .{ .cmpxchgIndex = cmpxchg_index }, |
| 4019 | }; | 4047 | }; |
| 4020 | }, | 4048 | }, |
| 4049 | .closure_get => { | ||
| 4050 | const captured, const scope = parent_scope.getCapture(extended.small); | ||
| 4051 | return self.walkInstruction(file, scope, parent_src, captured, need_type, call_ctx); | ||
| 4052 | }, | ||
| 4021 | } | 4053 | } |
| 4022 | }, | 4054 | }, |
| 4023 | } | 4055 | } |
src/InternPool.zig+1-2| ... | @@ -1,7 +1,6 @@ | ... | @@ -1,7 +1,6 @@ |
| 1 | //! All interned objects have both a value and a type. | 1 | //! All interned objects have both a value and a type. |
| 2 | //! This data structure is self-contained, with the following exceptions: | 2 | //! This data structure is self-contained, with the following exceptions: |
| 3 | //! * Module.Namespace has a pointer to Module.File | 3 | //! * Module.Namespace has a pointer to Module.File |
| 4 | //! * Module.Decl has a pointer to Module.CaptureScope | ||
| 5 | 4 | ||
| 6 | /// Maps `Key` to `Index`. `Key` objects are not stored anywhere; they are | 5 | /// Maps `Key` to `Index`. `Key` objects are not stored anywhere; they are |
| 7 | /// constructed lazily. | 6 | /// constructed lazily. |
| ... | @@ -6395,7 +6394,6 @@ fn finishFuncInstance( | ... | @@ -6395,7 +6394,6 @@ fn finishFuncInstance( |
| 6395 | .@"addrspace" = fn_owner_decl.@"addrspace", | 6394 | .@"addrspace" = fn_owner_decl.@"addrspace", |
| 6396 | .analysis = .complete, | 6395 | .analysis = .complete, |
| 6397 | .zir_decl_index = fn_owner_decl.zir_decl_index, | 6396 | .zir_decl_index = fn_owner_decl.zir_decl_index, |
| 6398 | .src_scope = fn_owner_decl.src_scope, | ||
| 6399 | .is_pub = fn_owner_decl.is_pub, | 6397 | .is_pub = fn_owner_decl.is_pub, |
| 6400 | .is_exported = fn_owner_decl.is_exported, | 6398 | .is_exported = fn_owner_decl.is_exported, |
| 6401 | .alive = true, | 6399 | .alive = true, |
| ... | @@ -7891,6 +7889,7 @@ pub fn destroyNamespace(ip: *InternPool, gpa: Allocator, index: NamespaceIndex) | ... | @@ -7891,6 +7889,7 @@ pub fn destroyNamespace(ip: *InternPool, gpa: Allocator, index: NamespaceIndex) |
| 7891 | .parent = undefined, | 7889 | .parent = undefined, |
| 7892 | .file_scope = undefined, | 7890 | .file_scope = undefined, |
| 7893 | .decl_index = undefined, | 7891 | .decl_index = undefined, |
| 7892 | .captures = undefined, | ||
| 7894 | }; | 7893 | }; |
| 7895 | ip.namespaces_free_list.append(gpa, index) catch { | 7894 | ip.namespaces_free_list.append(gpa, index) catch { |
| 7896 | // In order to keep `destroyNamespace` a non-fallible function, we ignore memory | 7895 | // In order to keep `destroyNamespace` a non-fallible function, we ignore memory |
src/Module.zig+48-52| ... | @@ -101,17 +101,6 @@ embed_table: std.StringArrayHashMapUnmanaged(*EmbedFile) = .{}, | ... | @@ -101,17 +101,6 @@ embed_table: std.StringArrayHashMapUnmanaged(*EmbedFile) = .{}, |
| 101 | /// is not yet implemented. | 101 | /// is not yet implemented. |
| 102 | intern_pool: InternPool = .{}, | 102 | intern_pool: InternPool = .{}, |
| 103 | 103 | ||
| 104 | /// The index type for this array is `CaptureScope.Index` and the elements here are | ||
| 105 | /// the indexes of the parent capture scopes. | ||
| 106 | /// Memory is owned by gpa; garbage collected. | ||
| 107 | capture_scope_parents: std.ArrayListUnmanaged(CaptureScope.Index) = .{}, | ||
| 108 | /// Value is index of type | ||
| 109 | /// Memory is owned by gpa; garbage collected. | ||
| 110 | runtime_capture_scopes: std.AutoArrayHashMapUnmanaged(CaptureScope.Key, InternPool.Index) = .{}, | ||
| 111 | /// Value is index of value | ||
| 112 | /// Memory is owned by gpa; garbage collected. | ||
| 113 | comptime_capture_scopes: std.AutoArrayHashMapUnmanaged(CaptureScope.Key, InternPool.Index) = .{}, | ||
| 114 | |||
| 115 | /// To be eliminated in a future commit by moving more data into InternPool. | 104 | /// To be eliminated in a future commit by moving more data into InternPool. |
| 116 | /// Current uses that must be eliminated: | 105 | /// Current uses that must be eliminated: |
| 117 | /// * comptime pointer mutation | 106 | /// * comptime pointer mutation |
| ... | @@ -305,28 +294,6 @@ pub const Export = struct { | ... | @@ -305,28 +294,6 @@ pub const Export = struct { |
| 305 | } | 294 | } |
| 306 | }; | 295 | }; |
| 307 | 296 | ||
| 308 | pub const CaptureScope = struct { | ||
| 309 | pub const Key = extern struct { | ||
| 310 | zir_index: Zir.Inst.Index, | ||
| 311 | index: Index, | ||
| 312 | }; | ||
| 313 | |||
| 314 | /// Index into `capture_scope_parents` which uniquely identifies a capture scope. | ||
| 315 | pub const Index = enum(u32) { | ||
| 316 | none = std.math.maxInt(u32), | ||
| 317 | _, | ||
| 318 | |||
| 319 | pub fn parent(i: Index, mod: *Module) Index { | ||
| 320 | return mod.capture_scope_parents.items[@intFromEnum(i)]; | ||
| 321 | } | ||
| 322 | }; | ||
| 323 | }; | ||
| 324 | |||
| 325 | pub fn createCaptureScope(mod: *Module, parent: CaptureScope.Index) error{OutOfMemory}!CaptureScope.Index { | ||
| 326 | try mod.capture_scope_parents.append(mod.gpa, parent); | ||
| 327 | return @enumFromInt(mod.capture_scope_parents.items.len - 1); | ||
| 328 | } | ||
| 329 | |||
| 330 | const ValueArena = struct { | 297 | const ValueArena = struct { |
| 331 | state: std.heap.ArenaAllocator.State, | 298 | state: std.heap.ArenaAllocator.State, |
| 332 | state_acquired: ?*std.heap.ArenaAllocator.State = null, | 299 | state_acquired: ?*std.heap.ArenaAllocator.State = null, |
| ... | @@ -386,9 +353,6 @@ pub const Decl = struct { | ... | @@ -386,9 +353,6 @@ pub const Decl = struct { |
| 386 | /// there is no parent. | 353 | /// there is no parent. |
| 387 | src_namespace: Namespace.Index, | 354 | src_namespace: Namespace.Index, |
| 388 | 355 | ||
| 389 | /// The scope which lexically contains this decl. | ||
| 390 | src_scope: CaptureScope.Index, | ||
| 391 | |||
| 392 | /// The AST node index of this declaration. | 356 | /// The AST node index of this declaration. |
| 393 | /// Must be recomputed when the corresponding source file is modified. | 357 | /// Must be recomputed when the corresponding source file is modified. |
| 394 | src_node: Ast.Node.Index, | 358 | src_node: Ast.Node.Index, |
| ... | @@ -792,11 +756,41 @@ pub const Namespace = struct { | ... | @@ -792,11 +756,41 @@ pub const Namespace = struct { |
| 792 | /// These are only declarations named directly by the AST; anonymous | 756 | /// These are only declarations named directly by the AST; anonymous |
| 793 | /// declarations are not stored here. | 757 | /// declarations are not stored here. |
| 794 | decls: std.ArrayHashMapUnmanaged(Decl.Index, void, DeclContext, true) = .{}, | 758 | decls: std.ArrayHashMapUnmanaged(Decl.Index, void, DeclContext, true) = .{}, |
| 795 | |||
| 796 | /// Key is usingnamespace Decl itself. To find the namespace being included, | 759 | /// Key is usingnamespace Decl itself. To find the namespace being included, |
| 797 | /// the Decl Value has to be resolved as a Type which has a Namespace. | 760 | /// the Decl Value has to be resolved as a Type which has a Namespace. |
| 798 | /// Value is whether the usingnamespace decl is marked `pub`. | 761 | /// Value is whether the usingnamespace decl is marked `pub`. |
| 799 | usingnamespace_set: std.AutoHashMapUnmanaged(Decl.Index, bool) = .{}, | 762 | usingnamespace_set: std.AutoHashMapUnmanaged(Decl.Index, bool) = .{}, |
| 763 | /// Allocated into `gpa`. | ||
| 764 | /// The ordered set of values captured in this type's closure. | ||
| 765 | /// `closure_get` instructions look up values in this list. | ||
| 766 | captures: []CaptureValue, | ||
| 767 | |||
| 768 | /// A single value captured in a container's closure. This is not an | ||
| 769 | /// `InternPool.Index` so we can differentiate between runtime-known values | ||
| 770 | /// (where only the type is comptime-known) and comptime-known values. | ||
| 771 | pub const CaptureValue = enum(u32) { | ||
| 772 | _, | ||
| 773 | pub const Unwrapped = union(enum) { | ||
| 774 | /// Index refers to the value. | ||
| 775 | @"comptime": InternPool.Index, | ||
| 776 | /// Index refers to the type. | ||
| 777 | runtime: InternPool.Index, | ||
| 778 | }; | ||
| 779 | pub fn wrap(val: Unwrapped) CaptureValue { | ||
| 780 | return switch (val) { | ||
| 781 | .@"comptime" => |i| @enumFromInt(@intFromEnum(i)), | ||
| 782 | .runtime => |i| @enumFromInt((1 << 31) | @intFromEnum(i)), | ||
| 783 | }; | ||
| 784 | } | ||
| 785 | pub fn unwrap(val: CaptureValue) Unwrapped { | ||
| 786 | const tag: u1 = @intCast(@intFromEnum(val) >> 31); | ||
| 787 | const raw = @intFromEnum(val); | ||
| 788 | return switch (tag) { | ||
| 789 | 0 => .{ .@"comptime" = @enumFromInt(raw) }, | ||
| 790 | 1 => .{ .runtime = @enumFromInt(@as(u31, @truncate(raw))) }, | ||
| 791 | }; | ||
| 792 | } | ||
| 793 | }; | ||
| 800 | 794 | ||
| 801 | const Index = InternPool.NamespaceIndex; | 795 | const Index = InternPool.NamespaceIndex; |
| 802 | const OptionalIndex = InternPool.OptionalNamespaceIndex; | 796 | const OptionalIndex = InternPool.OptionalNamespaceIndex; |
| ... | @@ -2135,15 +2129,12 @@ pub fn deinit(zcu: *Zcu) void { | ... | @@ -2135,15 +2129,12 @@ pub fn deinit(zcu: *Zcu) void { |
| 2135 | while (it.next()) |namespace| { | 2129 | while (it.next()) |namespace| { |
| 2136 | namespace.decls.deinit(gpa); | 2130 | namespace.decls.deinit(gpa); |
| 2137 | namespace.usingnamespace_set.deinit(gpa); | 2131 | namespace.usingnamespace_set.deinit(gpa); |
| 2132 | gpa.free(namespace.captures); | ||
| 2138 | } | 2133 | } |
| 2139 | } | 2134 | } |
| 2140 | 2135 | ||
| 2141 | zcu.intern_pool.deinit(gpa); | 2136 | zcu.intern_pool.deinit(gpa); |
| 2142 | zcu.tmp_hack_arena.deinit(); | 2137 | zcu.tmp_hack_arena.deinit(); |
| 2143 | |||
| 2144 | zcu.capture_scope_parents.deinit(gpa); | ||
| 2145 | zcu.runtime_capture_scopes.deinit(gpa); | ||
| 2146 | zcu.comptime_capture_scopes.deinit(gpa); | ||
| 2147 | } | 2138 | } |
| 2148 | 2139 | ||
| 2149 | pub fn destroyDecl(mod: *Module, decl_index: Decl.Index) void { | 2140 | pub fn destroyDecl(mod: *Module, decl_index: Decl.Index) void { |
| ... | @@ -3362,11 +3353,12 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void { | ... | @@ -3362,11 +3353,12 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void { |
| 3362 | .parent = .none, | 3353 | .parent = .none, |
| 3363 | .decl_index = undefined, | 3354 | .decl_index = undefined, |
| 3364 | .file_scope = file, | 3355 | .file_scope = file, |
| 3356 | .captures = &.{}, | ||
| 3365 | }); | 3357 | }); |
| 3366 | const new_namespace = mod.namespacePtr(new_namespace_index); | 3358 | const new_namespace = mod.namespacePtr(new_namespace_index); |
| 3367 | errdefer mod.destroyNamespace(new_namespace_index); | 3359 | errdefer mod.destroyNamespace(new_namespace_index); |
| 3368 | 3360 | ||
| 3369 | const new_decl_index = try mod.allocateNewDecl(new_namespace_index, 0, .none); | 3361 | const new_decl_index = try mod.allocateNewDecl(new_namespace_index, 0); |
| 3370 | const new_decl = mod.declPtr(new_decl_index); | 3362 | const new_decl = mod.declPtr(new_decl_index); |
| 3371 | errdefer @panic("TODO error handling"); | 3363 | errdefer @panic("TODO error handling"); |
| 3372 | 3364 | ||
| ... | @@ -3420,9 +3412,18 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void { | ... | @@ -3420,9 +3412,18 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void { |
| 3420 | const struct_ty = sema.getStructType( | 3412 | const struct_ty = sema.getStructType( |
| 3421 | new_decl_index, | 3413 | new_decl_index, |
| 3422 | new_namespace_index, | 3414 | new_namespace_index, |
| 3415 | null, | ||
| 3423 | try mod.intern_pool.trackZir(gpa, file, .main_struct_inst), | 3416 | try mod.intern_pool.trackZir(gpa, file, .main_struct_inst), |
| 3424 | ) catch |err| switch (err) { | 3417 | ) catch |err| switch (err) { |
| 3425 | error.OutOfMemory => return error.OutOfMemory, | 3418 | error.OutOfMemory => return error.OutOfMemory, |
| 3419 | // The following errors are from resolving capture values, but the root | ||
| 3420 | // struct of a file has no captures. | ||
| 3421 | error.AnalysisFail, | ||
| 3422 | error.NeededSourceLocation, | ||
| 3423 | error.GenericPoison, | ||
| 3424 | error.ComptimeReturn, | ||
| 3425 | error.ComptimeBreak, | ||
| 3426 | => unreachable, | ||
| 3426 | }; | 3427 | }; |
| 3427 | // TODO: figure out InternPool removals for incremental compilation | 3428 | // TODO: figure out InternPool removals for incremental compilation |
| 3428 | //errdefer ip.remove(struct_ty); | 3429 | //errdefer ip.remove(struct_ty); |
| ... | @@ -3573,7 +3574,6 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult { | ... | @@ -3573,7 +3574,6 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult { |
| 3573 | .sema = &sema, | 3574 | .sema = &sema, |
| 3574 | .src_decl = decl_index, | 3575 | .src_decl = decl_index, |
| 3575 | .namespace = decl.src_namespace, | 3576 | .namespace = decl.src_namespace, |
| 3576 | .wip_capture_scope = try mod.createCaptureScope(decl.src_scope), | ||
| 3577 | .instructions = .{}, | 3577 | .instructions = .{}, |
| 3578 | .inlining = null, | 3578 | .inlining = null, |
| 3579 | .is_comptime = true, | 3579 | .is_comptime = true, |
| ... | @@ -4205,7 +4205,7 @@ fn scanDecl(iter: *ScanDeclIter, decl_inst: Zir.Inst.Index) Allocator.Error!void | ... | @@ -4205,7 +4205,7 @@ fn scanDecl(iter: *ScanDeclIter, decl_inst: Zir.Inst.Index) Allocator.Error!void |
| 4205 | ); | 4205 | ); |
| 4206 | const comp = zcu.comp; | 4206 | const comp = zcu.comp; |
| 4207 | if (!gop.found_existing) { | 4207 | if (!gop.found_existing) { |
| 4208 | const new_decl_index = try zcu.allocateNewDecl(namespace_index, decl_node, iter.parent_decl.src_scope); | 4208 | const new_decl_index = try zcu.allocateNewDecl(namespace_index, decl_node); |
| 4209 | const new_decl = zcu.declPtr(new_decl_index); | 4209 | const new_decl = zcu.declPtr(new_decl_index); |
| 4210 | new_decl.kind = kind; | 4210 | new_decl.kind = kind; |
| 4211 | new_decl.name = decl_name; | 4211 | new_decl.name = decl_name; |
| ... | @@ -4438,7 +4438,6 @@ pub fn analyzeFnBody(mod: *Module, func_index: InternPool.Index, arena: Allocato | ... | @@ -4438,7 +4438,6 @@ pub fn analyzeFnBody(mod: *Module, func_index: InternPool.Index, arena: Allocato |
| 4438 | .sema = &sema, | 4438 | .sema = &sema, |
| 4439 | .src_decl = decl_index, | 4439 | .src_decl = decl_index, |
| 4440 | .namespace = decl.src_namespace, | 4440 | .namespace = decl.src_namespace, |
| 4441 | .wip_capture_scope = try mod.createCaptureScope(decl.src_scope), | ||
| 4442 | .instructions = .{}, | 4441 | .instructions = .{}, |
| 4443 | .inlining = null, | 4442 | .inlining = null, |
| 4444 | .is_comptime = false, | 4443 | .is_comptime = false, |
| ... | @@ -4639,7 +4638,6 @@ pub fn allocateNewDecl( | ... | @@ -4639,7 +4638,6 @@ pub fn allocateNewDecl( |
| 4639 | mod: *Module, | 4638 | mod: *Module, |
| 4640 | namespace: Namespace.Index, | 4639 | namespace: Namespace.Index, |
| 4641 | src_node: Ast.Node.Index, | 4640 | src_node: Ast.Node.Index, |
| 4642 | src_scope: CaptureScope.Index, | ||
| 4643 | ) !Decl.Index { | 4641 | ) !Decl.Index { |
| 4644 | const ip = &mod.intern_pool; | 4642 | const ip = &mod.intern_pool; |
| 4645 | const gpa = mod.gpa; | 4643 | const gpa = mod.gpa; |
| ... | @@ -4657,7 +4655,6 @@ pub fn allocateNewDecl( | ... | @@ -4657,7 +4655,6 @@ pub fn allocateNewDecl( |
| 4657 | .@"addrspace" = .generic, | 4655 | .@"addrspace" = .generic, |
| 4658 | .analysis = .unreferenced, | 4656 | .analysis = .unreferenced, |
| 4659 | .zir_decl_index = .none, | 4657 | .zir_decl_index = .none, |
| 4660 | .src_scope = src_scope, | ||
| 4661 | .is_pub = false, | 4658 | .is_pub = false, |
| 4662 | .is_exported = false, | 4659 | .is_exported = false, |
| 4663 | .alive = false, | 4660 | .alive = false, |
| ... | @@ -4697,17 +4694,16 @@ pub fn errorSetBits(mod: *Module) u16 { | ... | @@ -4697,17 +4694,16 @@ pub fn errorSetBits(mod: *Module) u16 { |
| 4697 | 4694 | ||
| 4698 | pub fn createAnonymousDecl(mod: *Module, block: *Sema.Block, typed_value: TypedValue) !Decl.Index { | 4695 | pub fn createAnonymousDecl(mod: *Module, block: *Sema.Block, typed_value: TypedValue) !Decl.Index { |
| 4699 | const src_decl = mod.declPtr(block.src_decl); | 4696 | const src_decl = mod.declPtr(block.src_decl); |
| 4700 | return mod.createAnonymousDeclFromDecl(src_decl, block.namespace, block.wip_capture_scope, typed_value); | 4697 | return mod.createAnonymousDeclFromDecl(src_decl, block.namespace, typed_value); |
| 4701 | } | 4698 | } |
| 4702 | 4699 | ||
| 4703 | pub fn createAnonymousDeclFromDecl( | 4700 | pub fn createAnonymousDeclFromDecl( |
| 4704 | mod: *Module, | 4701 | mod: *Module, |
| 4705 | src_decl: *Decl, | 4702 | src_decl: *Decl, |
| 4706 | namespace: Namespace.Index, | 4703 | namespace: Namespace.Index, |
| 4707 | src_scope: CaptureScope.Index, | ||
| 4708 | tv: TypedValue, | 4704 | tv: TypedValue, |
| 4709 | ) !Decl.Index { | 4705 | ) !Decl.Index { |
| 4710 | const new_decl_index = try mod.allocateNewDecl(namespace, src_decl.src_node, src_scope); | 4706 | const new_decl_index = try mod.allocateNewDecl(namespace, src_decl.src_node); |
| 4711 | errdefer mod.destroyDecl(new_decl_index); | 4707 | errdefer mod.destroyDecl(new_decl_index); |
| 4712 | const name = try mod.intern_pool.getOrPutStringFmt(mod.gpa, "{}__anon_{d}", .{ | 4708 | const name = try mod.intern_pool.getOrPutStringFmt(mod.gpa, "{}__anon_{d}", .{ |
| 4713 | src_decl.name.fmt(&mod.intern_pool), @intFromEnum(new_decl_index), | 4709 | src_decl.name.fmt(&mod.intern_pool), @intFromEnum(new_decl_index), |
| ... | @@ -5276,7 +5272,7 @@ pub fn populateTestFunctions( | ... | @@ -5276,7 +5272,7 @@ pub fn populateTestFunctions( |
| 5276 | .len = test_decl_name.len, | 5272 | .len = test_decl_name.len, |
| 5277 | .child = .u8_type, | 5273 | .child = .u8_type, |
| 5278 | }); | 5274 | }); |
| 5279 | const test_name_decl_index = try mod.createAnonymousDeclFromDecl(decl, decl.src_namespace, .none, .{ | 5275 | const test_name_decl_index = try mod.createAnonymousDeclFromDecl(decl, decl.src_namespace, .{ |
| 5280 | .ty = test_name_decl_ty, | 5276 | .ty = test_name_decl_ty, |
| 5281 | .val = Value.fromInterned((try mod.intern(.{ .aggregate = .{ | 5277 | .val = Value.fromInterned((try mod.intern(.{ .aggregate = .{ |
| 5282 | .ty = test_name_decl_ty.toIntern(), | 5278 | .ty = test_name_decl_ty.toIntern(), |
| ... | @@ -5322,7 +5318,7 @@ pub fn populateTestFunctions( | ... | @@ -5322,7 +5318,7 @@ pub fn populateTestFunctions( |
| 5322 | .child = test_fn_ty.toIntern(), | 5318 | .child = test_fn_ty.toIntern(), |
| 5323 | .sentinel = .none, | 5319 | .sentinel = .none, |
| 5324 | }); | 5320 | }); |
| 5325 | const array_decl_index = try mod.createAnonymousDeclFromDecl(decl, decl.src_namespace, .none, .{ | 5321 | const array_decl_index = try mod.createAnonymousDeclFromDecl(decl, decl.src_namespace, .{ |
| 5326 | .ty = array_decl_ty, | 5322 | .ty = array_decl_ty, |
| 5327 | .val = Value.fromInterned((try mod.intern(.{ .aggregate = .{ | 5323 | .val = Value.fromInterned((try mod.intern(.{ .aggregate = .{ |
| 5328 | .ty = array_decl_ty.toIntern(), | 5324 | .ty = array_decl_ty.toIntern(), |
src/Sema.zig+114-117| ... | @@ -155,7 +155,6 @@ const Namespace = Module.Namespace; | ... | @@ -155,7 +155,6 @@ const Namespace = Module.Namespace; |
| 155 | const CompileError = Module.CompileError; | 155 | const CompileError = Module.CompileError; |
| 156 | const SemaError = Module.SemaError; | 156 | const SemaError = Module.SemaError; |
| 157 | const Decl = Module.Decl; | 157 | const Decl = Module.Decl; |
| 158 | const CaptureScope = Module.CaptureScope; | ||
| 159 | const LazySrcLoc = std.zig.LazySrcLoc; | 158 | const LazySrcLoc = std.zig.LazySrcLoc; |
| 160 | const RangeSet = @import("RangeSet.zig"); | 159 | const RangeSet = @import("RangeSet.zig"); |
| 161 | const target_util = @import("target.zig"); | 160 | const target_util = @import("target.zig"); |
| ... | @@ -331,8 +330,6 @@ pub const Block = struct { | ... | @@ -331,8 +330,6 @@ pub const Block = struct { |
| 331 | /// used to add a `func_instance` into the `InternPool`. | 330 | /// used to add a `func_instance` into the `InternPool`. |
| 332 | params: std.MultiArrayList(Param) = .{}, | 331 | params: std.MultiArrayList(Param) = .{}, |
| 333 | 332 | ||
| 334 | wip_capture_scope: CaptureScope.Index, | ||
| 335 | |||
| 336 | label: ?*Label = null, | 333 | label: ?*Label = null, |
| 337 | inlining: ?*Inlining, | 334 | inlining: ?*Inlining, |
| 338 | /// If runtime_index is not 0 then one of these is guaranteed to be non null. | 335 | /// If runtime_index is not 0 then one of these is guaranteed to be non null. |
| ... | @@ -475,7 +472,6 @@ pub const Block = struct { | ... | @@ -475,7 +472,6 @@ pub const Block = struct { |
| 475 | .src_decl = parent.src_decl, | 472 | .src_decl = parent.src_decl, |
| 476 | .namespace = parent.namespace, | 473 | .namespace = parent.namespace, |
| 477 | .instructions = .{}, | 474 | .instructions = .{}, |
| 478 | .wip_capture_scope = parent.wip_capture_scope, | ||
| 479 | .label = null, | 475 | .label = null, |
| 480 | .inlining = parent.inlining, | 476 | .inlining = parent.inlining, |
| 481 | .is_comptime = parent.is_comptime, | 477 | .is_comptime = parent.is_comptime, |
| ... | @@ -974,12 +970,6 @@ fn analyzeBodyInner( | ... | @@ -974,12 +970,6 @@ fn analyzeBodyInner( |
| 974 | 970 | ||
| 975 | try sema.inst_map.ensureSpaceForInstructions(sema.gpa, body); | 971 | try sema.inst_map.ensureSpaceForInstructions(sema.gpa, body); |
| 976 | 972 | ||
| 977 | // Most of the time, we don't need to construct a new capture scope for a | ||
| 978 | // block. However, successive iterations of comptime loops can capture | ||
| 979 | // different values for the same Zir.Inst.Index, so in those cases, we will | ||
| 980 | // have to create nested capture scopes; see the `.repeat` case below. | ||
| 981 | const parent_capture_scope = block.wip_capture_scope; | ||
| 982 | |||
| 983 | const mod = sema.mod; | 973 | const mod = sema.mod; |
| 984 | const map = &sema.inst_map; | 974 | const map = &sema.inst_map; |
| 985 | const tags = sema.code.instructions.items(.tag); | 975 | const tags = sema.code.instructions.items(.tag); |
| ... | @@ -1028,7 +1018,6 @@ fn analyzeBodyInner( | ... | @@ -1028,7 +1018,6 @@ fn analyzeBodyInner( |
| 1028 | .c_import => try sema.zirCImport(block, inst), | 1018 | .c_import => try sema.zirCImport(block, inst), |
| 1029 | .call => try sema.zirCall(block, inst, .direct), | 1019 | .call => try sema.zirCall(block, inst, .direct), |
| 1030 | .field_call => try sema.zirCall(block, inst, .field), | 1020 | .field_call => try sema.zirCall(block, inst, .field), |
| 1031 | .closure_get => try sema.zirClosureGet(block, inst), | ||
| 1032 | .cmp_lt => try sema.zirCmp(block, inst, .lt), | 1021 | .cmp_lt => try sema.zirCmp(block, inst, .lt), |
| 1033 | .cmp_lte => try sema.zirCmp(block, inst, .lte), | 1022 | .cmp_lte => try sema.zirCmp(block, inst, .lte), |
| 1034 | .cmp_eq => try sema.zirCmpEq(block, inst, .eq, Air.Inst.Tag.fromCmpOp(.eq, block.float_mode == .Optimized)), | 1023 | .cmp_eq => try sema.zirCmpEq(block, inst, .eq, Air.Inst.Tag.fromCmpOp(.eq, block.float_mode == .Optimized)), |
| ... | @@ -1275,6 +1264,7 @@ fn analyzeBodyInner( | ... | @@ -1275,6 +1264,7 @@ fn analyzeBodyInner( |
| 1275 | .work_group_size => try sema.zirWorkItem( block, extended, extended.opcode), | 1264 | .work_group_size => try sema.zirWorkItem( block, extended, extended.opcode), |
| 1276 | .work_group_id => try sema.zirWorkItem( block, extended, extended.opcode), | 1265 | .work_group_id => try sema.zirWorkItem( block, extended, extended.opcode), |
| 1277 | .in_comptime => try sema.zirInComptime( block), | 1266 | .in_comptime => try sema.zirInComptime( block), |
| 1267 | .closure_get => try sema.zirClosureGet( block, extended), | ||
| 1278 | // zig fmt: on | 1268 | // zig fmt: on |
| 1279 | 1269 | ||
| 1280 | .fence => { | 1270 | .fence => { |
| ... | @@ -1453,11 +1443,6 @@ fn analyzeBodyInner( | ... | @@ -1453,11 +1443,6 @@ fn analyzeBodyInner( |
| 1453 | i += 1; | 1443 | i += 1; |
| 1454 | continue; | 1444 | continue; |
| 1455 | }, | 1445 | }, |
| 1456 | .closure_capture => { | ||
| 1457 | try sema.zirClosureCapture(block, inst); | ||
| 1458 | i += 1; | ||
| 1459 | continue; | ||
| 1460 | }, | ||
| 1461 | .memcpy => { | 1446 | .memcpy => { |
| 1462 | try sema.zirMemcpy(block, inst); | 1447 | try sema.zirMemcpy(block, inst); |
| 1463 | i += 1; | 1448 | i += 1; |
| ... | @@ -1534,11 +1519,6 @@ fn analyzeBodyInner( | ... | @@ -1534,11 +1519,6 @@ fn analyzeBodyInner( |
| 1534 | // Send comptime control flow back to the beginning of this block. | 1519 | // Send comptime control flow back to the beginning of this block. |
| 1535 | const src = LazySrcLoc.nodeOffset(datas[@intFromEnum(inst)].node); | 1520 | const src = LazySrcLoc.nodeOffset(datas[@intFromEnum(inst)].node); |
| 1536 | try sema.emitBackwardBranch(block, src); | 1521 | try sema.emitBackwardBranch(block, src); |
| 1537 | |||
| 1538 | // We need to construct new capture scopes for the next loop iteration so it | ||
| 1539 | // can capture values without clobbering the earlier iteration's captures. | ||
| 1540 | block.wip_capture_scope = try mod.createCaptureScope(parent_capture_scope); | ||
| 1541 | |||
| 1542 | i = 0; | 1522 | i = 0; |
| 1543 | continue; | 1523 | continue; |
| 1544 | } else { | 1524 | } else { |
| ... | @@ -1552,11 +1532,6 @@ fn analyzeBodyInner( | ... | @@ -1552,11 +1532,6 @@ fn analyzeBodyInner( |
| 1552 | // Send comptime control flow back to the beginning of this block. | 1532 | // Send comptime control flow back to the beginning of this block. |
| 1553 | const src = LazySrcLoc.nodeOffset(datas[@intFromEnum(inst)].node); | 1533 | const src = LazySrcLoc.nodeOffset(datas[@intFromEnum(inst)].node); |
| 1554 | try sema.emitBackwardBranch(block, src); | 1534 | try sema.emitBackwardBranch(block, src); |
| 1555 | |||
| 1556 | // We need to construct new capture scopes for the next loop iteration so it | ||
| 1557 | // can capture values without clobbering the earlier iteration's captures. | ||
| 1558 | block.wip_capture_scope = try mod.createCaptureScope(parent_capture_scope); | ||
| 1559 | |||
| 1560 | i = 0; | 1535 | i = 0; |
| 1561 | continue; | 1536 | continue; |
| 1562 | }, | 1537 | }, |
| ... | @@ -1855,10 +1830,6 @@ fn analyzeBodyInner( | ... | @@ -1855,10 +1830,6 @@ fn analyzeBodyInner( |
| 1855 | map.putAssumeCapacity(inst, air_inst); | 1830 | map.putAssumeCapacity(inst, air_inst); |
| 1856 | i += 1; | 1831 | i += 1; |
| 1857 | } | 1832 | } |
| 1858 | |||
| 1859 | // We may have overwritten the capture scope due to a `repeat` instruction where | ||
| 1860 | // the body had a capture; restore it now. | ||
| 1861 | block.wip_capture_scope = parent_capture_scope; | ||
| 1862 | } | 1833 | } |
| 1863 | 1834 | ||
| 1864 | pub fn resolveInstAllowNone(sema: *Sema, zir_ref: Zir.Inst.Ref) !Air.Inst.Ref { | 1835 | pub fn resolveInstAllowNone(sema: *Sema, zir_ref: Zir.Inst.Ref) !Air.Inst.Ref { |
| ... | @@ -2698,10 +2669,41 @@ fn analyzeAsInt( | ... | @@ -2698,10 +2669,41 @@ fn analyzeAsInt( |
| 2698 | return (try val.getUnsignedIntAdvanced(mod, sema)).?; | 2669 | return (try val.getUnsignedIntAdvanced(mod, sema)).?; |
| 2699 | } | 2670 | } |
| 2700 | 2671 | ||
| 2672 | /// Given a ZIR extra index which points to a list of `Zir.Inst.Capture`, | ||
| 2673 | /// resolves this into a list of `Namespace.CaptureValue` allocated by `gpa`. | ||
| 2674 | /// Caller owns returned memory. | ||
| 2675 | fn getCaptures(sema: *Sema, parent_namespace: ?InternPool.NamespaceIndex, extra_index: usize, captures_len: u32) ![]Namespace.CaptureValue { | ||
| 2676 | const gpa = sema.gpa; | ||
| 2677 | const parent_captures: []const Namespace.CaptureValue = if (parent_namespace) |p| parent: { | ||
| 2678 | break :parent sema.mod.namespacePtr(p).captures; | ||
| 2679 | } else &.{}; | ||
| 2680 | |||
| 2681 | const captures = try gpa.alloc(Namespace.CaptureValue, captures_len); | ||
| 2682 | errdefer gpa.free(captures); | ||
| 2683 | |||
| 2684 | for (sema.code.extra[extra_index..][0..captures_len], captures) |raw, *capture| { | ||
| 2685 | const zir_capture: Zir.Inst.Capture = @enumFromInt(raw); | ||
| 2686 | capture.* = switch (zir_capture.unwrap()) { | ||
| 2687 | .inst => |inst| Namespace.CaptureValue.wrap(capture: { | ||
| 2688 | const air_ref = try sema.resolveInst(inst.toRef()); | ||
| 2689 | if (try sema.resolveValue(air_ref)) |val| { | ||
| 2690 | break :capture .{ .@"comptime" = val.toIntern() }; | ||
| 2691 | } | ||
| 2692 | break :capture .{ .runtime = sema.typeOf(air_ref).toIntern() }; | ||
| 2693 | }), | ||
| 2694 | .nested => |parent_idx| parent_captures[parent_idx], | ||
| 2695 | }; | ||
| 2696 | } | ||
| 2697 | |||
| 2698 | return captures; | ||
| 2699 | } | ||
| 2700 | |||
| 2701 | pub fn getStructType( | 2701 | pub fn getStructType( |
| 2702 | sema: *Sema, | 2702 | sema: *Sema, |
| 2703 | decl: InternPool.DeclIndex, | 2703 | decl: InternPool.DeclIndex, |
| 2704 | namespace: InternPool.NamespaceIndex, | 2704 | namespace: InternPool.NamespaceIndex, |
| 2705 | /// The direct parent Namespace for resolving nested capture values. | ||
| 2706 | parent_namespace: ?InternPool.NamespaceIndex, | ||
| 2705 | tracked_inst: InternPool.TrackedInst.Index, | 2707 | tracked_inst: InternPool.TrackedInst.Index, |
| 2706 | ) !InternPool.Index { | 2708 | ) !InternPool.Index { |
| 2707 | const mod = sema.mod; | 2709 | const mod = sema.mod; |
| ... | @@ -2713,6 +2715,11 @@ pub fn getStructType( | ... | @@ -2713,6 +2715,11 @@ pub fn getStructType( |
| 2713 | const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small); | 2715 | const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small); |
| 2714 | 2716 | ||
| 2715 | var extra_index: usize = extended.operand + @typeInfo(Zir.Inst.StructDecl).Struct.fields.len; | 2717 | var extra_index: usize = extended.operand + @typeInfo(Zir.Inst.StructDecl).Struct.fields.len; |
| 2718 | const captures_len = if (small.has_captures_len) blk: { | ||
| 2719 | const captures_len = sema.code.extra[extra_index]; | ||
| 2720 | extra_index += 1; | ||
| 2721 | break :blk captures_len; | ||
| 2722 | } else 0; | ||
| 2716 | const fields_len = if (small.has_fields_len) blk: { | 2723 | const fields_len = if (small.has_fields_len) blk: { |
| 2717 | const fields_len = sema.code.extra[extra_index]; | 2724 | const fields_len = sema.code.extra[extra_index]; |
| 2718 | extra_index += 1; | 2725 | extra_index += 1; |
| ... | @@ -2724,6 +2731,9 @@ pub fn getStructType( | ... | @@ -2724,6 +2731,9 @@ pub fn getStructType( |
| 2724 | break :blk decls_len; | 2731 | break :blk decls_len; |
| 2725 | } else 0; | 2732 | } else 0; |
| 2726 | 2733 | ||
| 2734 | mod.namespacePtr(namespace).captures = try sema.getCaptures(parent_namespace, extra_index, captures_len); | ||
| 2735 | extra_index += captures_len; | ||
| 2736 | |||
| 2727 | if (small.has_backing_int) { | 2737 | if (small.has_backing_int) { |
| 2728 | const backing_int_body_len = sema.code.extra[extra_index]; | 2738 | const backing_int_body_len = sema.code.extra[extra_index]; |
| 2729 | extra_index += 1; // backing_int_body_len | 2739 | extra_index += 1; // backing_int_body_len |
| ... | @@ -2791,12 +2801,13 @@ fn zirStructDecl( | ... | @@ -2791,12 +2801,13 @@ fn zirStructDecl( |
| 2791 | .parent = block.namespace.toOptional(), | 2801 | .parent = block.namespace.toOptional(), |
| 2792 | .decl_index = new_decl_index, | 2802 | .decl_index = new_decl_index, |
| 2793 | .file_scope = block.getFileScope(mod), | 2803 | .file_scope = block.getFileScope(mod), |
| 2804 | .captures = &.{}, // Will be set by `getStructType` | ||
| 2794 | }); | 2805 | }); |
| 2795 | errdefer mod.destroyNamespace(new_namespace_index); | 2806 | errdefer mod.destroyNamespace(new_namespace_index); |
| 2796 | 2807 | ||
| 2797 | const struct_ty = ty: { | 2808 | const struct_ty = ty: { |
| 2798 | const tracked_inst = try ip.trackZir(mod.gpa, block.getFileScope(mod), inst); | 2809 | const tracked_inst = try ip.trackZir(mod.gpa, block.getFileScope(mod), inst); |
| 2799 | const ty = try sema.getStructType(new_decl_index, new_namespace_index, tracked_inst); | 2810 | const ty = try sema.getStructType(new_decl_index, new_namespace_index, block.namespace, tracked_inst); |
| 2800 | if (sema.builtin_type_target_index != .none) { | 2811 | if (sema.builtin_type_target_index != .none) { |
| 2801 | ip.resolveBuiltinType(sema.builtin_type_target_index, ty); | 2812 | ip.resolveBuiltinType(sema.builtin_type_target_index, ty); |
| 2802 | break :ty sema.builtin_type_target_index; | 2813 | break :ty sema.builtin_type_target_index; |
| ... | @@ -2827,10 +2838,9 @@ fn createAnonymousDeclTypeNamed( | ... | @@ -2827,10 +2838,9 @@ fn createAnonymousDeclTypeNamed( |
| 2827 | const ip = &mod.intern_pool; | 2838 | const ip = &mod.intern_pool; |
| 2828 | const gpa = sema.gpa; | 2839 | const gpa = sema.gpa; |
| 2829 | const namespace = block.namespace; | 2840 | const namespace = block.namespace; |
| 2830 | const src_scope = block.wip_capture_scope; | ||
| 2831 | const src_decl = mod.declPtr(block.src_decl); | 2841 | const src_decl = mod.declPtr(block.src_decl); |
| 2832 | const src_node = src_decl.relativeToNodeIndex(src.node_offset.x); | 2842 | const src_node = src_decl.relativeToNodeIndex(src.node_offset.x); |
| 2833 | const new_decl_index = try mod.allocateNewDecl(namespace, src_node, src_scope); | 2843 | const new_decl_index = try mod.allocateNewDecl(namespace, src_node); |
| 2834 | errdefer mod.destroyDecl(new_decl_index); | 2844 | errdefer mod.destroyDecl(new_decl_index); |
| 2835 | 2845 | ||
| 2836 | switch (name_strategy) { | 2846 | switch (name_strategy) { |
| ... | @@ -2935,6 +2945,12 @@ fn zirEnumDecl( | ... | @@ -2935,6 +2945,12 @@ fn zirEnumDecl( |
| 2935 | break :blk tag_type_ref; | 2945 | break :blk tag_type_ref; |
| 2936 | } else .none; | 2946 | } else .none; |
| 2937 | 2947 | ||
| 2948 | const captures_len = if (small.has_captures_len) blk: { | ||
| 2949 | const captures_len = sema.code.extra[extra_index]; | ||
| 2950 | extra_index += 1; | ||
| 2951 | break :blk captures_len; | ||
| 2952 | } else 0; | ||
| 2953 | |||
| 2938 | const body_len = if (small.has_body_len) blk: { | 2954 | const body_len = if (small.has_body_len) blk: { |
| 2939 | const body_len = sema.code.extra[extra_index]; | 2955 | const body_len = sema.code.extra[extra_index]; |
| 2940 | extra_index += 1; | 2956 | extra_index += 1; |
| ... | @@ -2974,10 +2990,14 @@ fn zirEnumDecl( | ... | @@ -2974,10 +2990,14 @@ fn zirEnumDecl( |
| 2974 | ); | 2990 | ); |
| 2975 | } | 2991 | } |
| 2976 | 2992 | ||
| 2993 | const captures = try sema.getCaptures(block.namespace, extra_index, captures_len); | ||
| 2994 | extra_index += captures_len; | ||
| 2995 | |||
| 2977 | const new_namespace_index = try mod.createNamespace(.{ | 2996 | const new_namespace_index = try mod.createNamespace(.{ |
| 2978 | .parent = block.namespace.toOptional(), | 2997 | .parent = block.namespace.toOptional(), |
| 2979 | .decl_index = new_decl_index, | 2998 | .decl_index = new_decl_index, |
| 2980 | .file_scope = block.getFileScope(mod), | 2999 | .file_scope = block.getFileScope(mod), |
| 3000 | .captures = captures, | ||
| 2981 | }); | 3001 | }); |
| 2982 | errdefer if (!done) mod.destroyNamespace(new_namespace_index); | 3002 | errdefer if (!done) mod.destroyNamespace(new_namespace_index); |
| 2983 | 3003 | ||
| ... | @@ -3054,7 +3074,6 @@ fn zirEnumDecl( | ... | @@ -3054,7 +3074,6 @@ fn zirEnumDecl( |
| 3054 | .sema = sema, | 3074 | .sema = sema, |
| 3055 | .src_decl = new_decl_index, | 3075 | .src_decl = new_decl_index, |
| 3056 | .namespace = new_namespace_index, | 3076 | .namespace = new_namespace_index, |
| 3057 | .wip_capture_scope = try mod.createCaptureScope(new_decl.src_scope), | ||
| 3058 | .instructions = .{}, | 3077 | .instructions = .{}, |
| 3059 | .inlining = null, | 3078 | .inlining = null, |
| 3060 | .is_comptime = true, | 3079 | .is_comptime = true, |
| ... | @@ -3197,6 +3216,11 @@ fn zirUnionDecl( | ... | @@ -3197,6 +3216,11 @@ fn zirUnionDecl( |
| 3197 | const src = extra.data.src(); | 3216 | const src = extra.data.src(); |
| 3198 | 3217 | ||
| 3199 | extra_index += @intFromBool(small.has_tag_type); | 3218 | extra_index += @intFromBool(small.has_tag_type); |
| 3219 | const captures_len = if (small.has_captures_len) blk: { | ||
| 3220 | const captures_len = sema.code.extra[extra_index]; | ||
| 3221 | extra_index += 1; | ||
| 3222 | break :blk captures_len; | ||
| 3223 | } else 0; | ||
| 3200 | extra_index += @intFromBool(small.has_body_len); | 3224 | extra_index += @intFromBool(small.has_body_len); |
| 3201 | const fields_len = if (small.has_fields_len) blk: { | 3225 | const fields_len = if (small.has_fields_len) blk: { |
| 3202 | const fields_len = sema.code.extra[extra_index]; | 3226 | const fields_len = sema.code.extra[extra_index]; |
| ... | @@ -3230,10 +3254,14 @@ fn zirUnionDecl( | ... | @@ -3230,10 +3254,14 @@ fn zirUnionDecl( |
| 3230 | ); | 3254 | ); |
| 3231 | } | 3255 | } |
| 3232 | 3256 | ||
| 3257 | const captures = try sema.getCaptures(block.namespace, extra_index, captures_len); | ||
| 3258 | extra_index += captures_len; | ||
| 3259 | |||
| 3233 | const new_namespace_index = try mod.createNamespace(.{ | 3260 | const new_namespace_index = try mod.createNamespace(.{ |
| 3234 | .parent = block.namespace.toOptional(), | 3261 | .parent = block.namespace.toOptional(), |
| 3235 | .decl_index = new_decl_index, | 3262 | .decl_index = new_decl_index, |
| 3236 | .file_scope = block.getFileScope(mod), | 3263 | .file_scope = block.getFileScope(mod), |
| 3264 | .captures = captures, | ||
| 3237 | }); | 3265 | }); |
| 3238 | errdefer mod.destroyNamespace(new_namespace_index); | 3266 | errdefer mod.destroyNamespace(new_namespace_index); |
| 3239 | 3267 | ||
| ... | @@ -3300,6 +3328,12 @@ fn zirOpaqueDecl( | ... | @@ -3300,6 +3328,12 @@ fn zirOpaqueDecl( |
| 3300 | 3328 | ||
| 3301 | const src = extra.data.src(); | 3329 | const src = extra.data.src(); |
| 3302 | 3330 | ||
| 3331 | const captures_len = if (small.has_captures_len) blk: { | ||
| 3332 | const captures_len = sema.code.extra[extra_index]; | ||
| 3333 | extra_index += 1; | ||
| 3334 | break :blk captures_len; | ||
| 3335 | } else 0; | ||
| 3336 | |||
| 3303 | const decls_len = if (small.has_decls_len) blk: { | 3337 | const decls_len = if (small.has_decls_len) blk: { |
| 3304 | const decls_len = sema.code.extra[extra_index]; | 3338 | const decls_len = sema.code.extra[extra_index]; |
| 3305 | extra_index += 1; | 3339 | extra_index += 1; |
| ... | @@ -3326,10 +3360,14 @@ fn zirOpaqueDecl( | ... | @@ -3326,10 +3360,14 @@ fn zirOpaqueDecl( |
| 3326 | ); | 3360 | ); |
| 3327 | } | 3361 | } |
| 3328 | 3362 | ||
| 3363 | const captures = try sema.getCaptures(block.namespace, extra_index, captures_len); | ||
| 3364 | extra_index += captures_len; | ||
| 3365 | |||
| 3329 | const new_namespace_index = try mod.createNamespace(.{ | 3366 | const new_namespace_index = try mod.createNamespace(.{ |
| 3330 | .parent = block.namespace.toOptional(), | 3367 | .parent = block.namespace.toOptional(), |
| 3331 | .decl_index = new_decl_index, | 3368 | .decl_index = new_decl_index, |
| 3332 | .file_scope = block.getFileScope(mod), | 3369 | .file_scope = block.getFileScope(mod), |
| 3370 | .captures = captures, | ||
| 3333 | }); | 3371 | }); |
| 3334 | errdefer mod.destroyNamespace(new_namespace_index); | 3372 | errdefer mod.destroyNamespace(new_namespace_index); |
| 3335 | 3373 | ||
| ... | @@ -5780,7 +5818,6 @@ fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileEr | ... | @@ -5780,7 +5818,6 @@ fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileEr |
| 5780 | .sema = sema, | 5818 | .sema = sema, |
| 5781 | .src_decl = parent_block.src_decl, | 5819 | .src_decl = parent_block.src_decl, |
| 5782 | .namespace = parent_block.namespace, | 5820 | .namespace = parent_block.namespace, |
| 5783 | .wip_capture_scope = parent_block.wip_capture_scope, | ||
| 5784 | .instructions = .{}, | 5821 | .instructions = .{}, |
| 5785 | .inlining = parent_block.inlining, | 5822 | .inlining = parent_block.inlining, |
| 5786 | .is_comptime = true, | 5823 | .is_comptime = true, |
| ... | @@ -5900,7 +5937,6 @@ fn zirBlock(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index, force_compt | ... | @@ -5900,7 +5937,6 @@ fn zirBlock(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index, force_compt |
| 5900 | .sema = sema, | 5937 | .sema = sema, |
| 5901 | .src_decl = parent_block.src_decl, | 5938 | .src_decl = parent_block.src_decl, |
| 5902 | .namespace = parent_block.namespace, | 5939 | .namespace = parent_block.namespace, |
| 5903 | .wip_capture_scope = parent_block.wip_capture_scope, | ||
| 5904 | .instructions = .{}, | 5940 | .instructions = .{}, |
| 5905 | .label = &label, | 5941 | .label = &label, |
| 5906 | .inlining = parent_block.inlining, | 5942 | .inlining = parent_block.inlining, |
| ... | @@ -7515,7 +7551,6 @@ fn analyzeCall( | ... | @@ -7515,7 +7551,6 @@ fn analyzeCall( |
| 7515 | .sema = sema, | 7551 | .sema = sema, |
| 7516 | .src_decl = module_fn.owner_decl, | 7552 | .src_decl = module_fn.owner_decl, |
| 7517 | .namespace = fn_owner_decl.src_namespace, | 7553 | .namespace = fn_owner_decl.src_namespace, |
| 7518 | .wip_capture_scope = try mod.createCaptureScope(fn_owner_decl.src_scope), | ||
| 7519 | .instructions = .{}, | 7554 | .instructions = .{}, |
| 7520 | .label = null, | 7555 | .label = null, |
| 7521 | .inlining = &inlining, | 7556 | .inlining = &inlining, |
| ... | @@ -8036,7 +8071,6 @@ fn instantiateGenericCall( | ... | @@ -8036,7 +8071,6 @@ fn instantiateGenericCall( |
| 8036 | .sema = &child_sema, | 8071 | .sema = &child_sema, |
| 8037 | .src_decl = generic_owner_func.owner_decl, | 8072 | .src_decl = generic_owner_func.owner_decl, |
| 8038 | .namespace = namespace_index, | 8073 | .namespace = namespace_index, |
| 8039 | .wip_capture_scope = try mod.createCaptureScope(fn_owner_decl.src_scope), | ||
| 8040 | .instructions = .{}, | 8074 | .instructions = .{}, |
| 8041 | .inlining = null, | 8075 | .inlining = null, |
| 8042 | .is_comptime = true, | 8076 | .is_comptime = true, |
| ... | @@ -11409,7 +11443,6 @@ fn zirSwitchBlockErrUnion(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp | ... | @@ -11409,7 +11443,6 @@ fn zirSwitchBlockErrUnion(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp |
| 11409 | .sema = sema, | 11443 | .sema = sema, |
| 11410 | .src_decl = block.src_decl, | 11444 | .src_decl = block.src_decl, |
| 11411 | .namespace = block.namespace, | 11445 | .namespace = block.namespace, |
| 11412 | .wip_capture_scope = block.wip_capture_scope, | ||
| 11413 | .instructions = .{}, | 11446 | .instructions = .{}, |
| 11414 | .label = &label, | 11447 | .label = &label, |
| 11415 | .inlining = block.inlining, | 11448 | .inlining = block.inlining, |
| ... | @@ -12117,7 +12150,6 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r | ... | @@ -12117,7 +12150,6 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r |
| 12117 | .sema = sema, | 12150 | .sema = sema, |
| 12118 | .src_decl = block.src_decl, | 12151 | .src_decl = block.src_decl, |
| 12119 | .namespace = block.namespace, | 12152 | .namespace = block.namespace, |
| 12120 | .wip_capture_scope = block.wip_capture_scope, | ||
| 12121 | .instructions = .{}, | 12153 | .instructions = .{}, |
| 12122 | .label = &label, | 12154 | .label = &label, |
| 12123 | .inlining = block.inlining, | 12155 | .inlining = block.inlining, |
| ... | @@ -12281,7 +12313,6 @@ fn analyzeSwitchRuntimeBlock( | ... | @@ -12281,7 +12313,6 @@ fn analyzeSwitchRuntimeBlock( |
| 12281 | extra_index += info.body_len; | 12313 | extra_index += info.body_len; |
| 12282 | 12314 | ||
| 12283 | case_block.instructions.shrinkRetainingCapacity(0); | 12315 | case_block.instructions.shrinkRetainingCapacity(0); |
| 12284 | case_block.wip_capture_scope = try mod.createCaptureScope(child_block.wip_capture_scope); | ||
| 12285 | 12316 | ||
| 12286 | const item = case_vals.items[scalar_i]; | 12317 | const item = case_vals.items[scalar_i]; |
| 12287 | // `item` is already guaranteed to be constant known. | 12318 | // `item` is already guaranteed to be constant known. |
| ... | @@ -12339,7 +12370,6 @@ fn analyzeSwitchRuntimeBlock( | ... | @@ -12339,7 +12370,6 @@ fn analyzeSwitchRuntimeBlock( |
| 12339 | case_val_idx += items_len; | 12370 | case_val_idx += items_len; |
| 12340 | 12371 | ||
| 12341 | case_block.instructions.shrinkRetainingCapacity(0); | 12372 | case_block.instructions.shrinkRetainingCapacity(0); |
| 12342 | case_block.wip_capture_scope = child_block.wip_capture_scope; | ||
| 12343 | 12373 | ||
| 12344 | // Generate all possible cases as scalar prongs. | 12374 | // Generate all possible cases as scalar prongs. |
| 12345 | if (info.is_inline) { | 12375 | if (info.is_inline) { |
| ... | @@ -12371,7 +12401,6 @@ fn analyzeSwitchRuntimeBlock( | ... | @@ -12371,7 +12401,6 @@ fn analyzeSwitchRuntimeBlock( |
| 12371 | const item_ref = Air.internedToRef(item.toIntern()); | 12401 | const item_ref = Air.internedToRef(item.toIntern()); |
| 12372 | 12402 | ||
| 12373 | case_block.instructions.shrinkRetainingCapacity(0); | 12403 | case_block.instructions.shrinkRetainingCapacity(0); |
| 12374 | case_block.wip_capture_scope = child_block.wip_capture_scope; | ||
| 12375 | 12404 | ||
| 12376 | if (emit_bb) sema.emitBackwardBranch(block, .unneeded) catch |err| switch (err) { | 12405 | if (emit_bb) sema.emitBackwardBranch(block, .unneeded) catch |err| switch (err) { |
| 12377 | error.NeededSourceLocation => { | 12406 | error.NeededSourceLocation => { |
| ... | @@ -12411,7 +12440,6 @@ fn analyzeSwitchRuntimeBlock( | ... | @@ -12411,7 +12440,6 @@ fn analyzeSwitchRuntimeBlock( |
| 12411 | cases_len += 1; | 12440 | cases_len += 1; |
| 12412 | 12441 | ||
| 12413 | case_block.instructions.shrinkRetainingCapacity(0); | 12442 | case_block.instructions.shrinkRetainingCapacity(0); |
| 12414 | case_block.wip_capture_scope = child_block.wip_capture_scope; | ||
| 12415 | 12443 | ||
| 12416 | const analyze_body = if (union_originally) blk: { | 12444 | const analyze_body = if (union_originally) blk: { |
| 12417 | const item_val = sema.resolveConstDefinedValue(block, .unneeded, item, undefined) catch unreachable; | 12445 | const item_val = sema.resolveConstDefinedValue(block, .unneeded, item, undefined) catch unreachable; |
| ... | @@ -12557,7 +12585,6 @@ fn analyzeSwitchRuntimeBlock( | ... | @@ -12557,7 +12585,6 @@ fn analyzeSwitchRuntimeBlock( |
| 12557 | defer gpa.free(cond_body); | 12585 | defer gpa.free(cond_body); |
| 12558 | 12586 | ||
| 12559 | case_block.instructions.shrinkRetainingCapacity(0); | 12587 | case_block.instructions.shrinkRetainingCapacity(0); |
| 12560 | case_block.wip_capture_scope = try mod.createCaptureScope(child_block.wip_capture_scope); | ||
| 12561 | 12588 | ||
| 12562 | const body = sema.code.bodySlice(extra_index, info.body_len); | 12589 | const body = sema.code.bodySlice(extra_index, info.body_len); |
| 12563 | extra_index += info.body_len; | 12590 | extra_index += info.body_len; |
| ... | @@ -12618,7 +12645,6 @@ fn analyzeSwitchRuntimeBlock( | ... | @@ -12618,7 +12645,6 @@ fn analyzeSwitchRuntimeBlock( |
| 12618 | const item_ref = Air.internedToRef(item_val.toIntern()); | 12645 | const item_ref = Air.internedToRef(item_val.toIntern()); |
| 12619 | 12646 | ||
| 12620 | case_block.instructions.shrinkRetainingCapacity(0); | 12647 | case_block.instructions.shrinkRetainingCapacity(0); |
| 12621 | case_block.wip_capture_scope = child_block.wip_capture_scope; | ||
| 12622 | 12648 | ||
| 12623 | const analyze_body = if (union_originally) blk: { | 12649 | const analyze_body = if (union_originally) blk: { |
| 12624 | const field_ty = maybe_union_ty.unionFieldType(item_val, mod).?; | 12650 | const field_ty = maybe_union_ty.unionFieldType(item_val, mod).?; |
| ... | @@ -12669,7 +12695,6 @@ fn analyzeSwitchRuntimeBlock( | ... | @@ -12669,7 +12695,6 @@ fn analyzeSwitchRuntimeBlock( |
| 12669 | const item_ref = Air.internedToRef(item_val); | 12695 | const item_ref = Air.internedToRef(item_val); |
| 12670 | 12696 | ||
| 12671 | case_block.instructions.shrinkRetainingCapacity(0); | 12697 | case_block.instructions.shrinkRetainingCapacity(0); |
| 12672 | case_block.wip_capture_scope = child_block.wip_capture_scope; | ||
| 12673 | 12698 | ||
| 12674 | if (emit_bb) try sema.emitBackwardBranch(block, special_prong_src); | 12699 | if (emit_bb) try sema.emitBackwardBranch(block, special_prong_src); |
| 12675 | emit_bb = true; | 12700 | emit_bb = true; |
| ... | @@ -12700,7 +12725,6 @@ fn analyzeSwitchRuntimeBlock( | ... | @@ -12700,7 +12725,6 @@ fn analyzeSwitchRuntimeBlock( |
| 12700 | const item_ref = Air.internedToRef(cur); | 12725 | const item_ref = Air.internedToRef(cur); |
| 12701 | 12726 | ||
| 12702 | case_block.instructions.shrinkRetainingCapacity(0); | 12727 | case_block.instructions.shrinkRetainingCapacity(0); |
| 12703 | case_block.wip_capture_scope = child_block.wip_capture_scope; | ||
| 12704 | 12728 | ||
| 12705 | if (emit_bb) try sema.emitBackwardBranch(block, special_prong_src); | 12729 | if (emit_bb) try sema.emitBackwardBranch(block, special_prong_src); |
| 12706 | emit_bb = true; | 12730 | emit_bb = true; |
| ... | @@ -12728,7 +12752,6 @@ fn analyzeSwitchRuntimeBlock( | ... | @@ -12728,7 +12752,6 @@ fn analyzeSwitchRuntimeBlock( |
| 12728 | cases_len += 1; | 12752 | cases_len += 1; |
| 12729 | 12753 | ||
| 12730 | case_block.instructions.shrinkRetainingCapacity(0); | 12754 | case_block.instructions.shrinkRetainingCapacity(0); |
| 12731 | case_block.wip_capture_scope = child_block.wip_capture_scope; | ||
| 12732 | 12755 | ||
| 12733 | if (emit_bb) try sema.emitBackwardBranch(block, special_prong_src); | 12756 | if (emit_bb) try sema.emitBackwardBranch(block, special_prong_src); |
| 12734 | emit_bb = true; | 12757 | emit_bb = true; |
| ... | @@ -12754,7 +12777,6 @@ fn analyzeSwitchRuntimeBlock( | ... | @@ -12754,7 +12777,6 @@ fn analyzeSwitchRuntimeBlock( |
| 12754 | cases_len += 1; | 12777 | cases_len += 1; |
| 12755 | 12778 | ||
| 12756 | case_block.instructions.shrinkRetainingCapacity(0); | 12779 | case_block.instructions.shrinkRetainingCapacity(0); |
| 12757 | case_block.wip_capture_scope = child_block.wip_capture_scope; | ||
| 12758 | 12780 | ||
| 12759 | if (emit_bb) try sema.emitBackwardBranch(block, special_prong_src); | 12781 | if (emit_bb) try sema.emitBackwardBranch(block, special_prong_src); |
| 12760 | emit_bb = true; | 12782 | emit_bb = true; |
| ... | @@ -12783,7 +12805,6 @@ fn analyzeSwitchRuntimeBlock( | ... | @@ -12783,7 +12805,6 @@ fn analyzeSwitchRuntimeBlock( |
| 12783 | }; | 12805 | }; |
| 12784 | 12806 | ||
| 12785 | case_block.instructions.shrinkRetainingCapacity(0); | 12807 | case_block.instructions.shrinkRetainingCapacity(0); |
| 12786 | case_block.wip_capture_scope = try mod.createCaptureScope(child_block.wip_capture_scope); | ||
| 12787 | 12808 | ||
| 12788 | if (mod.backendSupportsFeature(.is_named_enum_value) and | 12809 | if (mod.backendSupportsFeature(.is_named_enum_value) and |
| 12789 | special.body.len != 0 and block.wantSafety() and | 12810 | special.body.len != 0 and block.wantSafety() and |
| ... | @@ -17264,49 +17285,16 @@ fn zirThis( | ... | @@ -17264,49 +17285,16 @@ fn zirThis( |
| 17264 | return sema.analyzeDeclVal(block, src, this_decl_index); | 17285 | return sema.analyzeDeclVal(block, src, this_decl_index); |
| 17265 | } | 17286 | } |
| 17266 | 17287 | ||
| 17267 | fn zirClosureCapture(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { | 17288 | fn zirClosureGet(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref { |
| 17268 | const mod = sema.mod; | 17289 | const mod = sema.mod; |
| 17269 | const gpa = sema.gpa; | 17290 | const captures = mod.namespacePtr(block.namespace).captures; |
| 17270 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_tok; | ||
| 17271 | // Closures are not necessarily constant values. For example, the | ||
| 17272 | // code might do something like this: | ||
| 17273 | // fn foo(x: anytype) void { const S = struct {field: @TypeOf(x)}; } | ||
| 17274 | // ...in which case the closure_capture instruction has access to a runtime | ||
| 17275 | // value only. In such case only the type is saved into the scope. | ||
| 17276 | const operand = try sema.resolveInst(inst_data.operand); | ||
| 17277 | const ty = sema.typeOf(operand); | ||
| 17278 | const key: CaptureScope.Key = .{ | ||
| 17279 | .zir_index = inst, | ||
| 17280 | .index = block.wip_capture_scope, | ||
| 17281 | }; | ||
| 17282 | if (try sema.resolveValue(operand)) |val| { | ||
| 17283 | try mod.comptime_capture_scopes.put(gpa, key, try val.intern(ty, mod)); | ||
| 17284 | } else { | ||
| 17285 | try mod.runtime_capture_scopes.put(gpa, key, ty.toIntern()); | ||
| 17286 | } | ||
| 17287 | } | ||
| 17288 | 17291 | ||
| 17289 | fn zirClosureGet(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 17292 | const src_node: i32 = @bitCast(extended.operand); |
| 17290 | const mod = sema.mod; | 17293 | const src = LazySrcLoc.nodeOffset(src_node); |
| 17291 | //const ip = &mod.intern_pool; | 17294 | |
| 17292 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].inst_node; | 17295 | const capture_ty = switch (captures[extended.small].unwrap()) { |
| 17293 | var scope: CaptureScope.Index = mod.declPtr(block.src_decl).src_scope; | 17296 | .@"comptime" => |index| return Air.internedToRef(index), |
| 17294 | assert(scope != .none); | 17297 | .runtime => |index| index, |
| 17295 | // Note: The target closure must be in this scope list. | ||
| 17296 | // If it's not here, the zir is invalid, or the list is broken. | ||
| 17297 | const capture_ty = while (true) { | ||
| 17298 | // Note: We don't need to add a dependency here, because | ||
| 17299 | // decls always depend on their lexical parents. | ||
| 17300 | const key: CaptureScope.Key = .{ | ||
| 17301 | .zir_index = inst_data.inst, | ||
| 17302 | .index = scope, | ||
| 17303 | }; | ||
| 17304 | if (mod.comptime_capture_scopes.get(key)) |val| | ||
| 17305 | return Air.internedToRef(val); | ||
| 17306 | if (mod.runtime_capture_scopes.get(key)) |ty| | ||
| 17307 | break ty; | ||
| 17308 | scope = scope.parent(mod); | ||
| 17309 | assert(scope != .none); | ||
| 17310 | }; | 17298 | }; |
| 17311 | 17299 | ||
| 17312 | // The comptime case is handled already above. Runtime case below. | 17300 | // The comptime case is handled already above. Runtime case below. |
| ... | @@ -17322,15 +17310,15 @@ fn zirClosureGet(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! | ... | @@ -17322,15 +17310,15 @@ fn zirClosureGet(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! |
| 17322 | }); | 17310 | }); |
| 17323 | break :name null; | 17311 | break :name null; |
| 17324 | }; | 17312 | }; |
| 17325 | const node = sema.owner_decl.relativeToNodeIndex(inst_data.src_node); | 17313 | const node = sema.owner_decl.relativeToNodeIndex(src_node); |
| 17326 | const token = tree.nodes.items(.main_token)[node]; | 17314 | const token = tree.nodes.items(.main_token)[node]; |
| 17327 | break :name tree.tokenSlice(token); | 17315 | break :name tree.tokenSlice(token); |
| 17328 | }; | 17316 | }; |
| 17329 | 17317 | ||
| 17330 | const msg = if (name) |some| | 17318 | const msg = if (name) |some| |
| 17331 | try sema.errMsg(block, inst_data.src(), "'{s}' not accessible outside function scope", .{some}) | 17319 | try sema.errMsg(block, src, "'{s}' not accessible outside function scope", .{some}) |
| 17332 | else | 17320 | else |
| 17333 | try sema.errMsg(block, inst_data.src(), "variable not accessible outside function scope", .{}); | 17321 | try sema.errMsg(block, src, "variable not accessible outside function scope", .{}); |
| 17334 | errdefer msg.destroy(sema.gpa); | 17322 | errdefer msg.destroy(sema.gpa); |
| 17335 | 17323 | ||
| 17336 | // TODO add "declared here" note | 17324 | // TODO add "declared here" note |
| ... | @@ -17350,15 +17338,15 @@ fn zirClosureGet(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! | ... | @@ -17350,15 +17338,15 @@ fn zirClosureGet(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! |
| 17350 | }); | 17338 | }); |
| 17351 | break :name null; | 17339 | break :name null; |
| 17352 | }; | 17340 | }; |
| 17353 | const node = sema.owner_decl.relativeToNodeIndex(inst_data.src_node); | 17341 | const node = sema.owner_decl.relativeToNodeIndex(src_node); |
| 17354 | const token = tree.nodes.items(.main_token)[node]; | 17342 | const token = tree.nodes.items(.main_token)[node]; |
| 17355 | break :name tree.tokenSlice(token); | 17343 | break :name tree.tokenSlice(token); |
| 17356 | }; | 17344 | }; |
| 17357 | 17345 | ||
| 17358 | const msg = if (name) |some| | 17346 | const msg = if (name) |some| |
| 17359 | try sema.errMsg(block, inst_data.src(), "'{s}' not accessible from inner function", .{some}) | 17347 | try sema.errMsg(block, src, "'{s}' not accessible from inner function", .{some}) |
| 17360 | else | 17348 | else |
| 17361 | try sema.errMsg(block, inst_data.src(), "variable not accessible from inner function", .{}); | 17349 | try sema.errMsg(block, src, "variable not accessible from inner function", .{}); |
| 17362 | errdefer msg.destroy(sema.gpa); | 17350 | errdefer msg.destroy(sema.gpa); |
| 17363 | 17351 | ||
| 17364 | try sema.errNote(block, LazySrcLoc.nodeOffset(0), msg, "crossed function definition here", .{}); | 17352 | try sema.errNote(block, LazySrcLoc.nodeOffset(0), msg, "crossed function definition here", .{}); |
| ... | @@ -18631,7 +18619,6 @@ fn zirTypeofBuiltin(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr | ... | @@ -18631,7 +18619,6 @@ fn zirTypeofBuiltin(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr |
| 18631 | .sema = sema, | 18619 | .sema = sema, |
| 18632 | .src_decl = block.src_decl, | 18620 | .src_decl = block.src_decl, |
| 18633 | .namespace = block.namespace, | 18621 | .namespace = block.namespace, |
| 18634 | .wip_capture_scope = block.wip_capture_scope, | ||
| 18635 | .instructions = .{}, | 18622 | .instructions = .{}, |
| 18636 | .inlining = block.inlining, | 18623 | .inlining = block.inlining, |
| 18637 | .is_comptime = false, | 18624 | .is_comptime = false, |
| ... | @@ -18710,7 +18697,6 @@ fn zirTypeofPeer( | ... | @@ -18710,7 +18697,6 @@ fn zirTypeofPeer( |
| 18710 | .sema = sema, | 18697 | .sema = sema, |
| 18711 | .src_decl = block.src_decl, | 18698 | .src_decl = block.src_decl, |
| 18712 | .namespace = block.namespace, | 18699 | .namespace = block.namespace, |
| 18713 | .wip_capture_scope = block.wip_capture_scope, | ||
| 18714 | .instructions = .{}, | 18700 | .instructions = .{}, |
| 18715 | .inlining = block.inlining, | 18701 | .inlining = block.inlining, |
| 18716 | .is_comptime = false, | 18702 | .is_comptime = false, |
| ... | @@ -19186,7 +19172,6 @@ fn ensurePostHoc(sema: *Sema, block: *Block, dest_block: Zir.Inst.Index) !*Label | ... | @@ -19186,7 +19172,6 @@ fn ensurePostHoc(sema: *Sema, block: *Block, dest_block: Zir.Inst.Index) !*Label |
| 19186 | .sema = sema, | 19172 | .sema = sema, |
| 19187 | .src_decl = block.src_decl, | 19173 | .src_decl = block.src_decl, |
| 19188 | .namespace = block.namespace, | 19174 | .namespace = block.namespace, |
| 19189 | .wip_capture_scope = block.wip_capture_scope, | ||
| 19190 | .instructions = .{}, | 19175 | .instructions = .{}, |
| 19191 | .label = &labeled_block.label, | 19176 | .label = &labeled_block.label, |
| 19192 | .inlining = block.inlining, | 19177 | .inlining = block.inlining, |
| ... | @@ -21462,6 +21447,7 @@ fn zirReify( | ... | @@ -21462,6 +21447,7 @@ fn zirReify( |
| 21462 | .parent = block.namespace.toOptional(), | 21447 | .parent = block.namespace.toOptional(), |
| 21463 | .decl_index = new_decl_index, | 21448 | .decl_index = new_decl_index, |
| 21464 | .file_scope = block.getFileScope(mod), | 21449 | .file_scope = block.getFileScope(mod), |
| 21450 | .captures = &.{}, | ||
| 21465 | }); | 21451 | }); |
| 21466 | errdefer mod.destroyNamespace(new_namespace_index); | 21452 | errdefer mod.destroyNamespace(new_namespace_index); |
| 21467 | 21453 | ||
| ... | @@ -21670,6 +21656,7 @@ fn zirReify( | ... | @@ -21670,6 +21656,7 @@ fn zirReify( |
| 21670 | .parent = block.namespace.toOptional(), | 21656 | .parent = block.namespace.toOptional(), |
| 21671 | .decl_index = new_decl_index, | 21657 | .decl_index = new_decl_index, |
| 21672 | .file_scope = block.getFileScope(mod), | 21658 | .file_scope = block.getFileScope(mod), |
| 21659 | .captures = &.{}, | ||
| 21673 | }); | 21660 | }); |
| 21674 | errdefer mod.destroyNamespace(new_namespace_index); | 21661 | errdefer mod.destroyNamespace(new_namespace_index); |
| 21675 | 21662 | ||
| ... | @@ -25919,7 +25906,7 @@ fn zirBuiltinExtern( | ... | @@ -25919,7 +25906,7 @@ fn zirBuiltinExtern( |
| 25919 | 25906 | ||
| 25920 | // TODO check duplicate extern | 25907 | // TODO check duplicate extern |
| 25921 | 25908 | ||
| 25922 | const new_decl_index = try mod.allocateNewDecl(sema.owner_decl.src_namespace, sema.owner_decl.src_node, .none); | 25909 | const new_decl_index = try mod.allocateNewDecl(sema.owner_decl.src_namespace, sema.owner_decl.src_node); |
| 25923 | errdefer mod.destroyDecl(new_decl_index); | 25910 | errdefer mod.destroyDecl(new_decl_index); |
| 25924 | const new_decl = mod.declPtr(new_decl_index); | 25911 | const new_decl = mod.declPtr(new_decl_index); |
| 25925 | new_decl.name = options.name; | 25912 | new_decl.name = options.name; |
| ... | @@ -26515,7 +26502,6 @@ fn addSafetyCheck( | ... | @@ -26515,7 +26502,6 @@ fn addSafetyCheck( |
| 26515 | .sema = sema, | 26502 | .sema = sema, |
| 26516 | .src_decl = parent_block.src_decl, | 26503 | .src_decl = parent_block.src_decl, |
| 26517 | .namespace = parent_block.namespace, | 26504 | .namespace = parent_block.namespace, |
| 26518 | .wip_capture_scope = parent_block.wip_capture_scope, | ||
| 26519 | .instructions = .{}, | 26505 | .instructions = .{}, |
| 26520 | .inlining = parent_block.inlining, | 26506 | .inlining = parent_block.inlining, |
| 26521 | .is_comptime = false, | 26507 | .is_comptime = false, |
| ... | @@ -26624,7 +26610,6 @@ fn panicUnwrapError( | ... | @@ -26624,7 +26610,6 @@ fn panicUnwrapError( |
| 26624 | .sema = sema, | 26610 | .sema = sema, |
| 26625 | .src_decl = parent_block.src_decl, | 26611 | .src_decl = parent_block.src_decl, |
| 26626 | .namespace = parent_block.namespace, | 26612 | .namespace = parent_block.namespace, |
| 26627 | .wip_capture_scope = parent_block.wip_capture_scope, | ||
| 26628 | .instructions = .{}, | 26613 | .instructions = .{}, |
| 26629 | .inlining = parent_block.inlining, | 26614 | .inlining = parent_block.inlining, |
| 26630 | .is_comptime = false, | 26615 | .is_comptime = false, |
| ... | @@ -26741,7 +26726,6 @@ fn safetyCheckFormatted( | ... | @@ -26741,7 +26726,6 @@ fn safetyCheckFormatted( |
| 26741 | .sema = sema, | 26726 | .sema = sema, |
| 26742 | .src_decl = parent_block.src_decl, | 26727 | .src_decl = parent_block.src_decl, |
| 26743 | .namespace = parent_block.namespace, | 26728 | .namespace = parent_block.namespace, |
| 26744 | .wip_capture_scope = parent_block.wip_capture_scope, | ||
| 26745 | .instructions = .{}, | 26729 | .instructions = .{}, |
| 26746 | .inlining = parent_block.inlining, | 26730 | .inlining = parent_block.inlining, |
| 26747 | .is_comptime = false, | 26731 | .is_comptime = false, |
| ... | @@ -35766,7 +35750,6 @@ fn semaBackingIntType(mod: *Module, struct_type: InternPool.Key.StructType) Comp | ... | @@ -35766,7 +35750,6 @@ fn semaBackingIntType(mod: *Module, struct_type: InternPool.Key.StructType) Comp |
| 35766 | .sema = &sema, | 35750 | .sema = &sema, |
| 35767 | .src_decl = decl_index, | 35751 | .src_decl = decl_index, |
| 35768 | .namespace = struct_type.namespace.unwrap() orelse decl.src_namespace, | 35752 | .namespace = struct_type.namespace.unwrap() orelse decl.src_namespace, |
| 35769 | .wip_capture_scope = try mod.createCaptureScope(decl.src_scope), | ||
| 35770 | .instructions = .{}, | 35753 | .instructions = .{}, |
| 35771 | .inlining = null, | 35754 | .inlining = null, |
| 35772 | .is_comptime = true, | 35755 | .is_comptime = true, |
| ... | @@ -35789,9 +35772,16 @@ fn semaBackingIntType(mod: *Module, struct_type: InternPool.Key.StructType) Comp | ... | @@ -35789,9 +35772,16 @@ fn semaBackingIntType(mod: *Module, struct_type: InternPool.Key.StructType) Comp |
| 35789 | 35772 | ||
| 35790 | if (small.has_backing_int) { | 35773 | if (small.has_backing_int) { |
| 35791 | var extra_index: usize = extended.operand + @typeInfo(Zir.Inst.StructDecl).Struct.fields.len; | 35774 | var extra_index: usize = extended.operand + @typeInfo(Zir.Inst.StructDecl).Struct.fields.len; |
| 35775 | const captures_len = if (small.has_captures_len) blk: { | ||
| 35776 | const captures_len = zir.extra[extra_index]; | ||
| 35777 | extra_index += 1; | ||
| 35778 | break :blk captures_len; | ||
| 35779 | } else 0; | ||
| 35792 | extra_index += @intFromBool(small.has_fields_len); | 35780 | extra_index += @intFromBool(small.has_fields_len); |
| 35793 | extra_index += @intFromBool(small.has_decls_len); | 35781 | extra_index += @intFromBool(small.has_decls_len); |
| 35794 | 35782 | ||
| 35783 | extra_index += captures_len; | ||
| 35784 | |||
| 35795 | const backing_int_body_len = zir.extra[extra_index]; | 35785 | const backing_int_body_len = zir.extra[extra_index]; |
| 35796 | extra_index += 1; | 35786 | extra_index += 1; |
| 35797 | 35787 | ||
| ... | @@ -36500,6 +36490,12 @@ fn structZirInfo(zir: Zir, zir_index: Zir.Inst.Index) struct { | ... | @@ -36500,6 +36490,12 @@ fn structZirInfo(zir: Zir, zir_index: Zir.Inst.Index) struct { |
| 36500 | const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small); | 36490 | const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small); |
| 36501 | var extra_index: usize = extended.operand + @typeInfo(Zir.Inst.StructDecl).Struct.fields.len; | 36491 | var extra_index: usize = extended.operand + @typeInfo(Zir.Inst.StructDecl).Struct.fields.len; |
| 36502 | 36492 | ||
| 36493 | const captures_len = if (small.has_captures_len) blk: { | ||
| 36494 | const captures_len = zir.extra[extra_index]; | ||
| 36495 | extra_index += 1; | ||
| 36496 | break :blk captures_len; | ||
| 36497 | } else 0; | ||
| 36498 | |||
| 36503 | const fields_len = if (small.has_fields_len) blk: { | 36499 | const fields_len = if (small.has_fields_len) blk: { |
| 36504 | const fields_len = zir.extra[extra_index]; | 36500 | const fields_len = zir.extra[extra_index]; |
| 36505 | extra_index += 1; | 36501 | extra_index += 1; |
| ... | @@ -36512,6 +36508,8 @@ fn structZirInfo(zir: Zir, zir_index: Zir.Inst.Index) struct { | ... | @@ -36512,6 +36508,8 @@ fn structZirInfo(zir: Zir, zir_index: Zir.Inst.Index) struct { |
| 36512 | break :decls_len decls_len; | 36508 | break :decls_len decls_len; |
| 36513 | } else 0; | 36509 | } else 0; |
| 36514 | 36510 | ||
| 36511 | extra_index += captures_len; | ||
| 36512 | |||
| 36515 | // The backing integer cannot be handled until `resolveStructLayout()`. | 36513 | // The backing integer cannot be handled until `resolveStructLayout()`. |
| 36516 | if (small.has_backing_int) { | 36514 | if (small.has_backing_int) { |
| 36517 | const backing_int_body_len = zir.extra[extra_index]; | 36515 | const backing_int_body_len = zir.extra[extra_index]; |
| ... | @@ -36584,7 +36582,6 @@ fn semaStructFields( | ... | @@ -36584,7 +36582,6 @@ fn semaStructFields( |
| 36584 | .sema = &sema, | 36582 | .sema = &sema, |
| 36585 | .src_decl = decl_index, | 36583 | .src_decl = decl_index, |
| 36586 | .namespace = namespace_index, | 36584 | .namespace = namespace_index, |
| 36587 | .wip_capture_scope = try mod.createCaptureScope(decl.src_scope), | ||
| 36588 | .instructions = .{}, | 36585 | .instructions = .{}, |
| 36589 | .inlining = null, | 36586 | .inlining = null, |
| 36590 | .is_comptime = true, | 36587 | .is_comptime = true, |
| ... | @@ -36842,7 +36839,6 @@ fn semaStructFieldInits( | ... | @@ -36842,7 +36839,6 @@ fn semaStructFieldInits( |
| 36842 | .sema = &sema, | 36839 | .sema = &sema, |
| 36843 | .src_decl = decl_index, | 36840 | .src_decl = decl_index, |
| 36844 | .namespace = namespace_index, | 36841 | .namespace = namespace_index, |
| 36845 | .wip_capture_scope = try mod.createCaptureScope(decl.src_scope), | ||
| 36846 | .instructions = .{}, | 36842 | .instructions = .{}, |
| 36847 | .inlining = null, | 36843 | .inlining = null, |
| 36848 | .is_comptime = true, | 36844 | .is_comptime = true, |
| ... | @@ -36974,6 +36970,12 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Key.Un | ... | @@ -36974,6 +36970,12 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Key.Un |
| 36974 | break :blk ty_ref; | 36970 | break :blk ty_ref; |
| 36975 | } else .none; | 36971 | } else .none; |
| 36976 | 36972 | ||
| 36973 | const captures_len = if (small.has_captures_len) blk: { | ||
| 36974 | const captures_len = zir.extra[extra_index]; | ||
| 36975 | extra_index += 1; | ||
| 36976 | break :blk captures_len; | ||
| 36977 | } else 0; | ||
| 36978 | |||
| 36977 | const body_len = if (small.has_body_len) blk: { | 36979 | const body_len = if (small.has_body_len) blk: { |
| 36978 | const body_len = zir.extra[extra_index]; | 36980 | const body_len = zir.extra[extra_index]; |
| 36979 | extra_index += 1; | 36981 | extra_index += 1; |
| ... | @@ -36992,8 +36994,8 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Key.Un | ... | @@ -36992,8 +36994,8 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Key.Un |
| 36992 | break :decls_len decls_len; | 36994 | break :decls_len decls_len; |
| 36993 | } else 0; | 36995 | } else 0; |
| 36994 | 36996 | ||
| 36995 | // Skip over decls. | 36997 | // Skip over captures and decls. |
| 36996 | extra_index += decls_len; | 36998 | extra_index += captures_len + decls_len; |
| 36997 | 36999 | ||
| 36998 | const body = zir.bodySlice(extra_index, body_len); | 37000 | const body = zir.bodySlice(extra_index, body_len); |
| 36999 | extra_index += body.len; | 37001 | extra_index += body.len; |
| ... | @@ -37028,7 +37030,6 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Key.Un | ... | @@ -37028,7 +37030,6 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Key.Un |
| 37028 | .sema = &sema, | 37030 | .sema = &sema, |
| 37029 | .src_decl = decl_index, | 37031 | .src_decl = decl_index, |
| 37030 | .namespace = union_type.namespace, | 37032 | .namespace = union_type.namespace, |
| 37031 | .wip_capture_scope = try mod.createCaptureScope(decl.src_scope), | ||
| 37032 | .instructions = .{}, | 37033 | .instructions = .{}, |
| 37033 | .inlining = null, | 37034 | .inlining = null, |
| 37034 | .is_comptime = true, | 37035 | .is_comptime = true, |
| ... | @@ -37372,7 +37373,7 @@ fn generateUnionTagTypeNumbered( | ... | @@ -37372,7 +37373,7 @@ fn generateUnionTagTypeNumbered( |
| 37372 | const ip = &mod.intern_pool; | 37373 | const ip = &mod.intern_pool; |
| 37373 | 37374 | ||
| 37374 | const src_decl = mod.declPtr(block.src_decl); | 37375 | const src_decl = mod.declPtr(block.src_decl); |
| 37375 | const new_decl_index = try mod.allocateNewDecl(block.namespace, src_decl.src_node, block.wip_capture_scope); | 37376 | const new_decl_index = try mod.allocateNewDecl(block.namespace, src_decl.src_node); |
| 37376 | errdefer mod.destroyDecl(new_decl_index); | 37377 | errdefer mod.destroyDecl(new_decl_index); |
| 37377 | const fqn = try decl.fullyQualifiedName(mod); | 37378 | const fqn = try decl.fullyQualifiedName(mod); |
| 37378 | const name = try ip.getOrPutStringFmt(gpa, "@typeInfo({}).Union.tag_type.?", .{fqn.fmt(ip)}); | 37379 | const name = try ip.getOrPutStringFmt(gpa, "@typeInfo({}).Union.tag_type.?", .{fqn.fmt(ip)}); |
| ... | @@ -37425,7 +37426,7 @@ fn generateUnionTagTypeSimple( | ... | @@ -37425,7 +37426,7 @@ fn generateUnionTagTypeSimple( |
| 37425 | }; | 37426 | }; |
| 37426 | const fqn = try mod.declPtr(decl_index).fullyQualifiedName(mod); | 37427 | const fqn = try mod.declPtr(decl_index).fullyQualifiedName(mod); |
| 37427 | const src_decl = mod.declPtr(block.src_decl); | 37428 | const src_decl = mod.declPtr(block.src_decl); |
| 37428 | const new_decl_index = try mod.allocateNewDecl(block.namespace, src_decl.src_node, block.wip_capture_scope); | 37429 | const new_decl_index = try mod.allocateNewDecl(block.namespace, src_decl.src_node); |
| 37429 | errdefer mod.destroyDecl(new_decl_index); | 37430 | errdefer mod.destroyDecl(new_decl_index); |
| 37430 | const name = try ip.getOrPutStringFmt(gpa, "@typeInfo({}).Union.tag_type.?", .{fqn.fmt(ip)}); | 37431 | const name = try ip.getOrPutStringFmt(gpa, "@typeInfo({}).Union.tag_type.?", .{fqn.fmt(ip)}); |
| 37431 | try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, .{ | 37432 | try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, .{ |
| ... | @@ -37460,7 +37461,6 @@ fn generateUnionTagTypeSimple( | ... | @@ -37460,7 +37461,6 @@ fn generateUnionTagTypeSimple( |
| 37460 | } | 37461 | } |
| 37461 | 37462 | ||
| 37462 | fn getBuiltin(sema: *Sema, name: []const u8) CompileError!Air.Inst.Ref { | 37463 | fn getBuiltin(sema: *Sema, name: []const u8) CompileError!Air.Inst.Ref { |
| 37463 | const mod = sema.mod; | ||
| 37464 | const gpa = sema.gpa; | 37464 | const gpa = sema.gpa; |
| 37465 | const src = LazySrcLoc.nodeOffset(0); | 37465 | const src = LazySrcLoc.nodeOffset(0); |
| 37466 | 37466 | ||
| ... | @@ -37469,7 +37469,6 @@ fn getBuiltin(sema: *Sema, name: []const u8) CompileError!Air.Inst.Ref { | ... | @@ -37469,7 +37469,6 @@ fn getBuiltin(sema: *Sema, name: []const u8) CompileError!Air.Inst.Ref { |
| 37469 | .sema = sema, | 37469 | .sema = sema, |
| 37470 | .src_decl = sema.owner_decl_index, | 37470 | .src_decl = sema.owner_decl_index, |
| 37471 | .namespace = sema.owner_decl.src_namespace, | 37471 | .namespace = sema.owner_decl.src_namespace, |
| 37472 | .wip_capture_scope = try mod.createCaptureScope(sema.owner_decl.src_scope), | ||
| 37473 | .instructions = .{}, | 37472 | .instructions = .{}, |
| 37474 | .inlining = null, | 37473 | .inlining = null, |
| 37475 | .is_comptime = true, | 37474 | .is_comptime = true, |
| ... | @@ -37510,7 +37509,6 @@ fn getBuiltinDecl(sema: *Sema, block: *Block, name: []const u8) CompileError!Int | ... | @@ -37510,7 +37509,6 @@ fn getBuiltinDecl(sema: *Sema, block: *Block, name: []const u8) CompileError!Int |
| 37510 | } | 37509 | } |
| 37511 | 37510 | ||
| 37512 | fn getBuiltinType(sema: *Sema, name: []const u8) CompileError!Type { | 37511 | fn getBuiltinType(sema: *Sema, name: []const u8) CompileError!Type { |
| 37513 | const mod = sema.mod; | ||
| 37514 | const ty_inst = try sema.getBuiltin(name); | 37512 | const ty_inst = try sema.getBuiltin(name); |
| 37515 | 37513 | ||
| 37516 | var block: Block = .{ | 37514 | var block: Block = .{ |
| ... | @@ -37518,7 +37516,6 @@ fn getBuiltinType(sema: *Sema, name: []const u8) CompileError!Type { | ... | @@ -37518,7 +37516,6 @@ fn getBuiltinType(sema: *Sema, name: []const u8) CompileError!Type { |
| 37518 | .sema = sema, | 37516 | .sema = sema, |
| 37519 | .src_decl = sema.owner_decl_index, | 37517 | .src_decl = sema.owner_decl_index, |
| 37520 | .namespace = sema.owner_decl.src_namespace, | 37518 | .namespace = sema.owner_decl.src_namespace, |
| 37521 | .wip_capture_scope = try mod.createCaptureScope(sema.owner_decl.src_scope), | ||
| 37522 | .instructions = .{}, | 37519 | .instructions = .{}, |
| 37523 | .inlining = null, | 37520 | .inlining = null, |
| 37524 | .is_comptime = true, | 37521 | .is_comptime = true, |
src/print_zir.zig+96-5| ... | @@ -282,7 +282,6 @@ const Writer = struct { | ... | @@ -282,7 +282,6 @@ const Writer = struct { |
| 282 | 282 | ||
| 283 | .ref, | 283 | .ref, |
| 284 | .ret_implicit, | 284 | .ret_implicit, |
| 285 | .closure_capture, | ||
| 286 | .validate_ref_ty, | 285 | .validate_ref_ty, |
| 287 | => try self.writeUnTok(stream, inst), | 286 | => try self.writeUnTok(stream, inst), |
| 288 | 287 | ||
| ... | @@ -510,8 +509,6 @@ const Writer = struct { | ... | @@ -510,8 +509,6 @@ const Writer = struct { |
| 510 | 509 | ||
| 511 | .dbg_stmt => try self.writeDbgStmt(stream, inst), | 510 | .dbg_stmt => try self.writeDbgStmt(stream, inst), |
| 512 | 511 | ||
| 513 | .closure_get => try self.writeInstNode(stream, inst), | ||
| 514 | |||
| 515 | .@"defer" => try self.writeDefer(stream, inst), | 512 | .@"defer" => try self.writeDefer(stream, inst), |
| 516 | .defer_err_code => try self.writeDeferErrCode(stream, inst), | 513 | .defer_err_code => try self.writeDeferErrCode(stream, inst), |
| 517 | 514 | ||
| ... | @@ -611,6 +608,7 @@ const Writer = struct { | ... | @@ -611,6 +608,7 @@ const Writer = struct { |
| 611 | .ptr_cast_no_dest => try self.writePtrCastNoDest(stream, extended), | 608 | .ptr_cast_no_dest => try self.writePtrCastNoDest(stream, extended), |
| 612 | 609 | ||
| 613 | .restore_err_ret_index => try self.writeRestoreErrRetIndex(stream, extended), | 610 | .restore_err_ret_index => try self.writeRestoreErrRetIndex(stream, extended), |
| 611 | .closure_get => try self.writeClosureGet(stream, extended), | ||
| 614 | } | 612 | } |
| 615 | } | 613 | } |
| 616 | 614 | ||
| ... | @@ -1401,6 +1399,12 @@ const Writer = struct { | ... | @@ -1401,6 +1399,12 @@ const Writer = struct { |
| 1401 | 1399 | ||
| 1402 | var extra_index: usize = extra.end; | 1400 | var extra_index: usize = extra.end; |
| 1403 | 1401 | ||
| 1402 | const captures_len = if (small.has_captures_len) blk: { | ||
| 1403 | const captures_len = self.code.extra[extra_index]; | ||
| 1404 | extra_index += 1; | ||
| 1405 | break :blk captures_len; | ||
| 1406 | } else 0; | ||
| 1407 | |||
| 1404 | const fields_len = if (small.has_fields_len) blk: { | 1408 | const fields_len = if (small.has_fields_len) blk: { |
| 1405 | const fields_len = self.code.extra[extra_index]; | 1409 | const fields_len = self.code.extra[extra_index]; |
| 1406 | extra_index += 1; | 1410 | extra_index += 1; |
| ... | @@ -1419,12 +1423,26 @@ const Writer = struct { | ... | @@ -1419,12 +1423,26 @@ const Writer = struct { |
| 1419 | 1423 | ||
| 1420 | try stream.print("{s}, ", .{@tagName(small.name_strategy)}); | 1424 | try stream.print("{s}, ", .{@tagName(small.name_strategy)}); |
| 1421 | 1425 | ||
| 1422 | if (small.layout == .Packed and small.has_backing_int) { | 1426 | if (captures_len == 0) { |
| 1427 | try stream.writeAll("{}, "); | ||
| 1428 | } else { | ||
| 1429 | try stream.writeAll("{ "); | ||
| 1430 | try self.writeCapture(stream, @enumFromInt(self.code.extra[extra_index])); | ||
| 1431 | extra_index += 1; | ||
| 1432 | for (1..captures_len) |_| { | ||
| 1433 | try stream.writeAll(", "); | ||
| 1434 | try self.writeCapture(stream, @enumFromInt(self.code.extra[extra_index])); | ||
| 1435 | extra_index += 1; | ||
| 1436 | } | ||
| 1437 | try stream.writeAll(" }, "); | ||
| 1438 | } | ||
| 1439 | |||
| 1440 | if (small.has_backing_int) { | ||
| 1423 | const backing_int_body_len = self.code.extra[extra_index]; | 1441 | const backing_int_body_len = self.code.extra[extra_index]; |
| 1424 | extra_index += 1; | 1442 | extra_index += 1; |
| 1425 | try stream.writeAll("Packed("); | 1443 | try stream.writeAll("Packed("); |
| 1426 | if (backing_int_body_len == 0) { | 1444 | if (backing_int_body_len == 0) { |
| 1427 | const backing_int_ref = @as(Zir.Inst.Ref, @enumFromInt(self.code.extra[extra_index])); | 1445 | const backing_int_ref: Zir.Inst.Ref = @enumFromInt(self.code.extra[extra_index]); |
| 1428 | extra_index += 1; | 1446 | extra_index += 1; |
| 1429 | try self.writeInstRef(stream, backing_int_ref); | 1447 | try self.writeInstRef(stream, backing_int_ref); |
| 1430 | } else { | 1448 | } else { |
| ... | @@ -1601,6 +1619,12 @@ const Writer = struct { | ... | @@ -1601,6 +1619,12 @@ const Writer = struct { |
| 1601 | break :blk tag_type_ref; | 1619 | break :blk tag_type_ref; |
| 1602 | } else .none; | 1620 | } else .none; |
| 1603 | 1621 | ||
| 1622 | const captures_len = if (small.has_captures_len) blk: { | ||
| 1623 | const captures_len = self.code.extra[extra_index]; | ||
| 1624 | extra_index += 1; | ||
| 1625 | break :blk captures_len; | ||
| 1626 | } else 0; | ||
| 1627 | |||
| 1604 | const body_len = if (small.has_body_len) blk: { | 1628 | const body_len = if (small.has_body_len) blk: { |
| 1605 | const body_len = self.code.extra[extra_index]; | 1629 | const body_len = self.code.extra[extra_index]; |
| 1606 | extra_index += 1; | 1630 | extra_index += 1; |
| ... | @@ -1624,6 +1648,20 @@ const Writer = struct { | ... | @@ -1624,6 +1648,20 @@ const Writer = struct { |
| 1624 | }); | 1648 | }); |
| 1625 | try self.writeFlag(stream, "autoenum, ", small.auto_enum_tag); | 1649 | try self.writeFlag(stream, "autoenum, ", small.auto_enum_tag); |
| 1626 | 1650 | ||
| 1651 | if (captures_len == 0) { | ||
| 1652 | try stream.writeAll("{}, "); | ||
| 1653 | } else { | ||
| 1654 | try stream.writeAll("{ "); | ||
| 1655 | try self.writeCapture(stream, @enumFromInt(self.code.extra[extra_index])); | ||
| 1656 | extra_index += 1; | ||
| 1657 | for (1..captures_len) |_| { | ||
| 1658 | try stream.writeAll(", "); | ||
| 1659 | try self.writeCapture(stream, @enumFromInt(self.code.extra[extra_index])); | ||
| 1660 | extra_index += 1; | ||
| 1661 | } | ||
| 1662 | try stream.writeAll(" }, "); | ||
| 1663 | } | ||
| 1664 | |||
| 1627 | if (decls_len == 0) { | 1665 | if (decls_len == 0) { |
| 1628 | try stream.writeAll("{}"); | 1666 | try stream.writeAll("{}"); |
| 1629 | } else { | 1667 | } else { |
| ... | @@ -1748,6 +1786,12 @@ const Writer = struct { | ... | @@ -1748,6 +1786,12 @@ const Writer = struct { |
| 1748 | break :blk tag_type_ref; | 1786 | break :blk tag_type_ref; |
| 1749 | } else .none; | 1787 | } else .none; |
| 1750 | 1788 | ||
| 1789 | const captures_len = if (small.has_captures_len) blk: { | ||
| 1790 | const captures_len = self.code.extra[extra_index]; | ||
| 1791 | extra_index += 1; | ||
| 1792 | break :blk captures_len; | ||
| 1793 | } else 0; | ||
| 1794 | |||
| 1751 | const body_len = if (small.has_body_len) blk: { | 1795 | const body_len = if (small.has_body_len) blk: { |
| 1752 | const body_len = self.code.extra[extra_index]; | 1796 | const body_len = self.code.extra[extra_index]; |
| 1753 | extra_index += 1; | 1797 | extra_index += 1; |
| ... | @@ -1769,6 +1813,20 @@ const Writer = struct { | ... | @@ -1769,6 +1813,20 @@ const Writer = struct { |
| 1769 | try stream.print("{s}, ", .{@tagName(small.name_strategy)}); | 1813 | try stream.print("{s}, ", .{@tagName(small.name_strategy)}); |
| 1770 | try self.writeFlag(stream, "nonexhaustive, ", small.nonexhaustive); | 1814 | try self.writeFlag(stream, "nonexhaustive, ", small.nonexhaustive); |
| 1771 | 1815 | ||
| 1816 | if (captures_len == 0) { | ||
| 1817 | try stream.writeAll("{}, "); | ||
| 1818 | } else { | ||
| 1819 | try stream.writeAll("{ "); | ||
| 1820 | try self.writeCapture(stream, @enumFromInt(self.code.extra[extra_index])); | ||
| 1821 | extra_index += 1; | ||
| 1822 | for (1..captures_len) |_| { | ||
| 1823 | try stream.writeAll(", "); | ||
| 1824 | try self.writeCapture(stream, @enumFromInt(self.code.extra[extra_index])); | ||
| 1825 | extra_index += 1; | ||
| 1826 | } | ||
| 1827 | try stream.writeAll(" }, "); | ||
| 1828 | } | ||
| 1829 | |||
| 1772 | if (decls_len == 0) { | 1830 | if (decls_len == 0) { |
| 1773 | try stream.writeAll("{}, "); | 1831 | try stream.writeAll("{}, "); |
| 1774 | } else { | 1832 | } else { |
| ... | @@ -1854,6 +1912,12 @@ const Writer = struct { | ... | @@ -1854,6 +1912,12 @@ const Writer = struct { |
| 1854 | const extra = self.code.extraData(Zir.Inst.OpaqueDecl, extended.operand); | 1912 | const extra = self.code.extraData(Zir.Inst.OpaqueDecl, extended.operand); |
| 1855 | var extra_index: usize = extra.end; | 1913 | var extra_index: usize = extra.end; |
| 1856 | 1914 | ||
| 1915 | const captures_len = if (small.has_captures_len) blk: { | ||
| 1916 | const captures_len = self.code.extra[extra_index]; | ||
| 1917 | extra_index += 1; | ||
| 1918 | break :blk captures_len; | ||
| 1919 | } else 0; | ||
| 1920 | |||
| 1857 | const decls_len = if (small.has_decls_len) blk: { | 1921 | const decls_len = if (small.has_decls_len) blk: { |
| 1858 | const decls_len = self.code.extra[extra_index]; | 1922 | const decls_len = self.code.extra[extra_index]; |
| 1859 | extra_index += 1; | 1923 | extra_index += 1; |
| ... | @@ -1862,6 +1926,20 @@ const Writer = struct { | ... | @@ -1862,6 +1926,20 @@ const Writer = struct { |
| 1862 | 1926 | ||
| 1863 | try stream.print("{s}, ", .{@tagName(small.name_strategy)}); | 1927 | try stream.print("{s}, ", .{@tagName(small.name_strategy)}); |
| 1864 | 1928 | ||
| 1929 | if (captures_len == 0) { | ||
| 1930 | try stream.writeAll("{}, "); | ||
| 1931 | } else { | ||
| 1932 | try stream.writeAll("{ "); | ||
| 1933 | try self.writeCapture(stream, @enumFromInt(self.code.extra[extra_index])); | ||
| 1934 | extra_index += 1; | ||
| 1935 | for (1..captures_len) |_| { | ||
| 1936 | try stream.writeAll(", "); | ||
| 1937 | try self.writeCapture(stream, @enumFromInt(self.code.extra[extra_index])); | ||
| 1938 | extra_index += 1; | ||
| 1939 | } | ||
| 1940 | try stream.writeAll(" }, "); | ||
| 1941 | } | ||
| 1942 | |||
| 1865 | if (decls_len == 0) { | 1943 | if (decls_len == 0) { |
| 1866 | try stream.writeAll("{})"); | 1944 | try stream.writeAll("{})"); |
| 1867 | } else { | 1945 | } else { |
| ... | @@ -2706,6 +2784,12 @@ const Writer = struct { | ... | @@ -2706,6 +2784,12 @@ const Writer = struct { |
| 2706 | try self.writeSrc(stream, inst_data.src()); | 2784 | try self.writeSrc(stream, inst_data.src()); |
| 2707 | } | 2785 | } |
| 2708 | 2786 | ||
| 2787 | fn writeClosureGet(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void { | ||
| 2788 | const src = LazySrcLoc.nodeOffset(@bitCast(extended.operand)); | ||
| 2789 | try stream.print("{d})) ", .{extended.small}); | ||
| 2790 | try self.writeSrc(stream, src); | ||
| 2791 | } | ||
| 2792 | |||
| 2709 | fn writeInstRef(self: *Writer, stream: anytype, ref: Zir.Inst.Ref) !void { | 2793 | fn writeInstRef(self: *Writer, stream: anytype, ref: Zir.Inst.Ref) !void { |
| 2710 | if (ref == .none) { | 2794 | if (ref == .none) { |
| 2711 | return stream.writeAll(".none"); | 2795 | return stream.writeAll(".none"); |
| ... | @@ -2722,6 +2806,13 @@ const Writer = struct { | ... | @@ -2722,6 +2806,13 @@ const Writer = struct { |
| 2722 | return stream.print("%{d}", .{@intFromEnum(inst)}); | 2806 | return stream.print("%{d}", .{@intFromEnum(inst)}); |
| 2723 | } | 2807 | } |
| 2724 | 2808 | ||
| 2809 | fn writeCapture(self: *Writer, stream: anytype, capture: Zir.Inst.Capture) !void { | ||
| 2810 | switch (capture.unwrap()) { | ||
| 2811 | .inst => |inst| return self.writeInstIndex(stream, inst), | ||
| 2812 | .nested => |i| return stream.print("[{d}]", .{i}), | ||
| 2813 | } | ||
| 2814 | } | ||
| 2815 | |||
| 2725 | fn writeOptionalInstRef( | 2816 | fn writeOptionalInstRef( |
| 2726 | self: *Writer, | 2817 | self: *Writer, |
| 2727 | stream: anytype, | 2818 | stream: anytype, |