| ... | @@ -889,17 +889,18 @@ fn analyzeBodyInner( | ... | @@ -889,17 +889,18 @@ fn analyzeBodyInner( |
| 889 | | 889 | |
| 890 | try sema.inst_map.ensureSpaceForInstructions(sema.gpa, body); | 890 | try sema.inst_map.ensureSpaceForInstructions(sema.gpa, body); |
| 891 | | 891 | |
| | 892 | // Most of the time, we don't need to construct a new capture scope for a |
| | 893 | // block. However, successive iterations of comptime loops can capture |
| | 894 | // different values for the same Zir.Inst.Index, so in those cases, we will |
| | 895 | // have to create nested capture scopes; see the `.repeat` case below. |
| 892 | const parent_capture_scope = block.wip_capture_scope; | 896 | const parent_capture_scope = block.wip_capture_scope; |
| 893 | | 897 | parent_capture_scope.incRef(); |
| 894 | var wip_captures = WipCaptureScope{ | 898 | var wip_captures: WipCaptureScope = .{ |
| 895 | .finalized = true, | | |
| 896 | .scope = parent_capture_scope, | 899 | .scope = parent_capture_scope, |
| 897 | .perm_arena = sema.perm_arena, | | |
| 898 | .gpa = sema.gpa, | 900 | .gpa = sema.gpa, |
| | 901 | .finalized = true, // don't finalize the parent scope |
| 899 | }; | 902 | }; |
| 900 | defer if (wip_captures.scope != parent_capture_scope) { | 903 | defer wip_captures.deinit(); |
| 901 | wip_captures.deinit(); | | |
| 902 | }; | | |
| 903 | | 904 | |
| 904 | const mod = sema.mod; | 905 | const mod = sema.mod; |
| 905 | const map = &sema.inst_map; | 906 | const map = &sema.inst_map; |
| ... | @@ -1452,6 +1453,11 @@ fn analyzeBodyInner( | ... | @@ -1452,6 +1453,11 @@ fn analyzeBodyInner( |
| 1452 | const src = LazySrcLoc.nodeOffset(datas[inst].node); | 1453 | const src = LazySrcLoc.nodeOffset(datas[inst].node); |
| 1453 | try sema.emitBackwardBranch(block, src); | 1454 | try sema.emitBackwardBranch(block, src); |
| 1454 | if (wip_captures.scope.captures.count() != orig_captures) { | 1455 | if (wip_captures.scope.captures.count() != orig_captures) { |
| | 1456 | // We need to construct new capture scopes for the next loop iteration so it |
| | 1457 | // can capture values without clobbering the earlier iteration's captures. |
| | 1458 | // At first, we reused the parent capture scope as an optimization, but for |
| | 1459 | // successive scopes we have to create new ones as children of the parent |
| | 1460 | // scope. |
| 1455 | try wip_captures.reset(parent_capture_scope); | 1461 | try wip_captures.reset(parent_capture_scope); |
| 1456 | block.wip_capture_scope = wip_captures.scope; | 1462 | block.wip_capture_scope = wip_captures.scope; |
| 1457 | orig_captures = 0; | 1463 | orig_captures = 0; |
| ... | @@ -1467,6 +1473,11 @@ fn analyzeBodyInner( | ... | @@ -1467,6 +1473,11 @@ fn analyzeBodyInner( |
| 1467 | const src = LazySrcLoc.nodeOffset(datas[inst].node); | 1473 | const src = LazySrcLoc.nodeOffset(datas[inst].node); |
| 1468 | try sema.emitBackwardBranch(block, src); | 1474 | try sema.emitBackwardBranch(block, src); |
| 1469 | if (wip_captures.scope.captures.count() != orig_captures) { | 1475 | if (wip_captures.scope.captures.count() != orig_captures) { |
| | 1476 | // We need to construct new capture scopes for the next loop iteration so it |
| | 1477 | // can capture values without clobbering the earlier iteration's captures. |
| | 1478 | // At first, we reused the parent capture scope as an optimization, but for |
| | 1479 | // successive scopes we have to create new ones as children of the parent |
| | 1480 | // scope. |
| 1470 | try wip_captures.reset(parent_capture_scope); | 1481 | try wip_captures.reset(parent_capture_scope); |
| 1471 | block.wip_capture_scope = wip_captures.scope; | 1482 | block.wip_capture_scope = wip_captures.scope; |
| 1472 | orig_captures = 0; | 1483 | orig_captures = 0; |
| ... | @@ -1749,6 +1760,8 @@ fn analyzeBodyInner( | ... | @@ -1749,6 +1760,8 @@ fn analyzeBodyInner( |
| 1749 | if (noreturn_inst) |some| try block.instructions.append(sema.gpa, some); | 1760 | if (noreturn_inst) |some| try block.instructions.append(sema.gpa, some); |
| 1750 | | 1761 | |
| 1751 | if (!wip_captures.finalized) { | 1762 | if (!wip_captures.finalized) { |
| | 1763 | // We've updated the capture scope due to a `repeat` instruction where |
| | 1764 | // the body had a capture; finalize our child scope and reset |
| 1752 | try wip_captures.finalize(); | 1765 | try wip_captures.finalize(); |
| 1753 | block.wip_capture_scope = parent_capture_scope; | 1766 | block.wip_capture_scope = parent_capture_scope; |
| 1754 | } | 1767 | } |
| ... | @@ -3007,7 +3020,7 @@ fn zirEnumDecl( | ... | @@ -3007,7 +3020,7 @@ fn zirEnumDecl( |
| 3007 | defer sema.func = prev_func; | 3020 | defer sema.func = prev_func; |
| 3008 | defer sema.func_index = prev_func_index; | 3021 | defer sema.func_index = prev_func_index; |
| 3009 | | 3022 | |
| 3010 | var wip_captures = try WipCaptureScope.init(gpa, sema.perm_arena, new_decl.src_scope); | 3023 | var wip_captures = try WipCaptureScope.init(gpa, new_decl.src_scope); |
| 3011 | defer wip_captures.deinit(); | 3024 | defer wip_captures.deinit(); |
| 3012 | | 3025 | |
| 3013 | var enum_block: Block = .{ | 3026 | var enum_block: Block = .{ |
| ... | @@ -6888,7 +6901,7 @@ fn analyzeCall( | ... | @@ -6888,7 +6901,7 @@ fn analyzeCall( |
| 6888 | sema.error_return_trace_index_on_fn_entry = block.error_return_trace_index; | 6901 | sema.error_return_trace_index_on_fn_entry = block.error_return_trace_index; |
| 6889 | defer sema.error_return_trace_index_on_fn_entry = parent_err_ret_index; | 6902 | defer sema.error_return_trace_index_on_fn_entry = parent_err_ret_index; |
| 6890 | | 6903 | |
| 6891 | var wip_captures = try WipCaptureScope.init(gpa, sema.perm_arena, fn_owner_decl.src_scope); | 6904 | var wip_captures = try WipCaptureScope.init(gpa, fn_owner_decl.src_scope); |
| 6892 | defer wip_captures.deinit(); | 6905 | defer wip_captures.deinit(); |
| 6893 | | 6906 | |
| 6894 | var child_block: Block = .{ | 6907 | var child_block: Block = .{ |
| ... | @@ -7751,7 +7764,7 @@ fn resolveGenericInstantiationType( | ... | @@ -7751,7 +7764,7 @@ fn resolveGenericInstantiationType( |
| 7751 | }; | 7764 | }; |
| 7752 | defer child_sema.deinit(); | 7765 | defer child_sema.deinit(); |
| 7753 | | 7766 | |
| 7754 | var wip_captures = try WipCaptureScope.init(gpa, sema.perm_arena, new_decl.src_scope); | 7767 | var wip_captures = try WipCaptureScope.init(gpa, new_decl.src_scope); |
| 7755 | defer wip_captures.deinit(); | 7768 | defer wip_captures.deinit(); |
| 7756 | | 7769 | |
| 7757 | var child_block: Block = .{ | 7770 | var child_block: Block = .{ |
| ... | @@ -11151,7 +11164,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError | ... | @@ -11151,7 +11164,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 11151 | const body = sema.code.extra[extra_index..][0..body_len]; | 11164 | const body = sema.code.extra[extra_index..][0..body_len]; |
| 11152 | extra_index += body_len; | 11165 | extra_index += body_len; |
| 11153 | | 11166 | |
| 11154 | var wip_captures = try WipCaptureScope.init(gpa, sema.perm_arena, child_block.wip_capture_scope); | 11167 | var wip_captures = try WipCaptureScope.init(gpa, child_block.wip_capture_scope); |
| 11155 | defer wip_captures.deinit(); | 11168 | defer wip_captures.deinit(); |
| 11156 | | 11169 | |
| 11157 | case_block.instructions.shrinkRetainingCapacity(0); | 11170 | case_block.instructions.shrinkRetainingCapacity(0); |
| ... | @@ -11396,7 +11409,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError | ... | @@ -11396,7 +11409,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 11396 | var cond_body = try case_block.instructions.toOwnedSlice(gpa); | 11409 | var cond_body = try case_block.instructions.toOwnedSlice(gpa); |
| 11397 | defer gpa.free(cond_body); | 11410 | defer gpa.free(cond_body); |
| 11398 | | 11411 | |
| 11399 | var wip_captures = try WipCaptureScope.init(gpa, sema.perm_arena, child_block.wip_capture_scope); | 11412 | var wip_captures = try WipCaptureScope.init(gpa, child_block.wip_capture_scope); |
| 11400 | defer wip_captures.deinit(); | 11413 | defer wip_captures.deinit(); |
| 11401 | | 11414 | |
| 11402 | case_block.instructions.shrinkRetainingCapacity(0); | 11415 | case_block.instructions.shrinkRetainingCapacity(0); |
| ... | @@ -11577,7 +11590,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError | ... | @@ -11577,7 +11590,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 11577 | }), | 11590 | }), |
| 11578 | }; | 11591 | }; |
| 11579 | | 11592 | |
| 11580 | var wip_captures = try WipCaptureScope.init(gpa, sema.perm_arena, child_block.wip_capture_scope); | 11593 | var wip_captures = try WipCaptureScope.init(gpa, child_block.wip_capture_scope); |
| 11581 | defer wip_captures.deinit(); | 11594 | defer wip_captures.deinit(); |
| 11582 | | 11595 | |
| 11583 | case_block.instructions.shrinkRetainingCapacity(0); | 11596 | case_block.instructions.shrinkRetainingCapacity(0); |
| ... | @@ -15720,13 +15733,15 @@ fn zirClosureCapture( | ... | @@ -15720,13 +15733,15 @@ fn zirClosureCapture( |
| 15720 | // ...in which case the closure_capture instruction has access to a runtime | 15733 | // ...in which case the closure_capture instruction has access to a runtime |
| 15721 | // value only. In such case we preserve the type and use a dummy runtime value. | 15734 | // value only. In such case we preserve the type and use a dummy runtime value. |
| 15722 | const operand = try sema.resolveInst(inst_data.operand); | 15735 | const operand = try sema.resolveInst(inst_data.operand); |
| 15723 | const val = (try sema.resolveMaybeUndefValAllowVariables(operand)) orelse | 15736 | const ty = sema.typeOf(operand); |
| 15724 | Value.@"unreachable"; | 15737 | const capture: CaptureScope.Capture = blk: { |
| 15725 | | 15738 | if (try sema.resolveMaybeUndefValAllowVariables(operand)) |val| { |
| 15726 | try block.wip_capture_scope.captures.putNoClobber(sema.gpa, inst, .{ | 15739 | const ip_index = try val.intern(ty, sema.mod); |
| 15727 | .ty = sema.typeOf(operand), | 15740 | break :blk .{ .comptime_val = ip_index }; |
| 15728 | .val = try val.copy(sema.perm_arena), | 15741 | } |
| 15729 | }); | 15742 | break :blk .{ .runtime_val = ty.toIntern() }; |
| | 15743 | }; |
| | 15744 | try block.wip_capture_scope.captures.putNoClobber(sema.gpa, inst, capture); |
| 15730 | } | 15745 | } |
| 15731 | | 15746 | |
| 15732 | fn zirClosureGet( | 15747 | fn zirClosureGet( |
| ... | @@ -15740,7 +15755,7 @@ fn zirClosureGet( | ... | @@ -15740,7 +15755,7 @@ fn zirClosureGet( |
| 15740 | var scope: *CaptureScope = mod.declPtr(block.src_decl).src_scope.?; | 15755 | var scope: *CaptureScope = mod.declPtr(block.src_decl).src_scope.?; |
| 15741 | // Note: The target closure must be in this scope list. | 15756 | // Note: The target closure must be in this scope list. |
| 15742 | // If it's not here, the zir is invalid, or the list is broken. | 15757 | // If it's not here, the zir is invalid, or the list is broken. |
| 15743 | const tv = while (true) { | 15758 | const capture = while (true) { |
| 15744 | // Note: We don't need to add a dependency here, because | 15759 | // Note: We don't need to add a dependency here, because |
| 15745 | // decls always depend on their lexical parents. | 15760 | // decls always depend on their lexical parents. |
| 15746 | | 15761 | |
| ... | @@ -15753,13 +15768,13 @@ fn zirClosureGet( | ... | @@ -15753,13 +15768,13 @@ fn zirClosureGet( |
| 15753 | } | 15768 | } |
| 15754 | return error.AnalysisFail; | 15769 | return error.AnalysisFail; |
| 15755 | } | 15770 | } |
| 15756 | if (scope.captures.getPtr(inst_data.inst)) |tv| { | 15771 | if (scope.captures.get(inst_data.inst)) |capture| { |
| 15757 | break tv; | 15772 | break capture; |
| 15758 | } | 15773 | } |
| 15759 | scope = scope.parent.?; | 15774 | scope = scope.parent.?; |
| 15760 | }; | 15775 | }; |
| 15761 | | 15776 | |
| 15762 | if (tv.val.toIntern() == .unreachable_value and !block.is_typeof and sema.func_index == .none) { | 15777 | if (capture == .runtime_val and !block.is_typeof and sema.func_index == .none) { |
| 15763 | const msg = msg: { | 15778 | const msg = msg: { |
| 15764 | const name = name: { | 15779 | const name = name: { |
| 15765 | const file = sema.owner_decl.getFileScope(mod); | 15780 | const file = sema.owner_decl.getFileScope(mod); |
| ... | @@ -15787,7 +15802,7 @@ fn zirClosureGet( | ... | @@ -15787,7 +15802,7 @@ fn zirClosureGet( |
| 15787 | return sema.failWithOwnedErrorMsg(msg); | 15802 | return sema.failWithOwnedErrorMsg(msg); |
| 15788 | } | 15803 | } |
| 15789 | | 15804 | |
| 15790 | if (tv.val.toIntern() == .unreachable_value and !block.is_typeof and !block.is_comptime and sema.func_index != .none) { | 15805 | if (capture == .runtime_val and !block.is_typeof and !block.is_comptime and sema.func_index != .none) { |
| 15791 | const msg = msg: { | 15806 | const msg = msg: { |
| 15792 | const name = name: { | 15807 | const name = name: { |
| 15793 | const file = sema.owner_decl.getFileScope(mod); | 15808 | const file = sema.owner_decl.getFileScope(mod); |
| ... | @@ -15817,13 +15832,17 @@ fn zirClosureGet( | ... | @@ -15817,13 +15832,17 @@ fn zirClosureGet( |
| 15817 | return sema.failWithOwnedErrorMsg(msg); | 15832 | return sema.failWithOwnedErrorMsg(msg); |
| 15818 | } | 15833 | } |
| 15819 | | 15834 | |
| 15820 | if (tv.val.toIntern() == .unreachable_value) { | 15835 | switch (capture) { |
| 15821 | assert(block.is_typeof); | 15836 | .runtime_val => |ty_ip_index| { |
| 15822 | // We need a dummy runtime instruction with the correct type. | 15837 | assert(block.is_typeof); |
| 15823 | return block.addTy(.alloc, tv.ty); | 15838 | // We need a dummy runtime instruction with the correct type. |
| | 15839 | return block.addTy(.alloc, ty_ip_index.toType()); |
| | 15840 | }, |
| | 15841 | .comptime_val => |val_ip_index| { |
| | 15842 | const ty = mod.intern_pool.typeOf(val_ip_index).toType(); |
| | 15843 | return sema.addConstant(ty, val_ip_index.toValue()); |
| | 15844 | }, |
| 15824 | } | 15845 | } |
| 15825 | | | |
| 15826 | return sema.addConstant(tv.ty, tv.val); | | |
| 15827 | } | 15846 | } |
| 15828 | | 15847 | |
| 15829 | fn zirRetAddr( | 15848 | fn zirRetAddr( |
| ... | @@ -31838,7 +31857,7 @@ fn semaBackingIntType(mod: *Module, struct_obj: *Module.Struct) CompileError!voi | ... | @@ -31838,7 +31857,7 @@ fn semaBackingIntType(mod: *Module, struct_obj: *Module.Struct) CompileError!voi |
| 31838 | var sema: Sema = .{ .mod = mod, .gpa = gpa, .arena = analysis_arena.allocator(), .perm_arena = decl_arena_allocator, .code = zir, .owner_decl = decl, .owner_decl_index = decl_index, .func = null, .func_index = .none, .fn_ret_ty = Type.void, .owner_func = null, .owner_func_index = .none }; | 31857 | var sema: Sema = .{ .mod = mod, .gpa = gpa, .arena = analysis_arena.allocator(), .perm_arena = decl_arena_allocator, .code = zir, .owner_decl = decl, .owner_decl_index = decl_index, .func = null, .func_index = .none, .fn_ret_ty = Type.void, .owner_func = null, .owner_func_index = .none }; |
| 31839 | defer sema.deinit(); | 31858 | defer sema.deinit(); |
| 31840 | | 31859 | |
| 31841 | var wip_captures = try WipCaptureScope.init(gpa, decl_arena_allocator, decl.src_scope); | 31860 | var wip_captures = try WipCaptureScope.init(gpa, decl.src_scope); |
| 31842 | defer wip_captures.deinit(); | 31861 | defer wip_captures.deinit(); |
| 31843 | | 31862 | |
| 31844 | var block: Block = .{ | 31863 | var block: Block = .{ |
| ... | @@ -32591,7 +32610,7 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void | ... | @@ -32591,7 +32610,7 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void |
| 32591 | }; | 32610 | }; |
| 32592 | defer sema.deinit(); | 32611 | defer sema.deinit(); |
| 32593 | | 32612 | |
| 32594 | var wip_captures = try WipCaptureScope.init(gpa, decl_arena_allocator, decl.src_scope); | 32613 | var wip_captures = try WipCaptureScope.init(gpa, decl.src_scope); |
| 32595 | defer wip_captures.deinit(); | 32614 | defer wip_captures.deinit(); |
| 32596 | | 32615 | |
| 32597 | var block_scope: Block = .{ | 32616 | var block_scope: Block = .{ |
| ... | @@ -32933,7 +32952,7 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void { | ... | @@ -32933,7 +32952,7 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void { |
| 32933 | }; | 32952 | }; |
| 32934 | defer sema.deinit(); | 32953 | defer sema.deinit(); |
| 32935 | | 32954 | |
| 32936 | var wip_captures = try WipCaptureScope.init(gpa, decl_arena_allocator, decl.src_scope); | 32955 | var wip_captures = try WipCaptureScope.init(gpa, decl.src_scope); |
| 32937 | defer wip_captures.deinit(); | 32956 | defer wip_captures.deinit(); |
| 32938 | | 32957 | |
| 32939 | var block_scope: Block = .{ | 32958 | var block_scope: Block = .{ |
| ... | @@ -33360,7 +33379,7 @@ fn generateUnionTagTypeSimple( | ... | @@ -33360,7 +33379,7 @@ fn generateUnionTagTypeSimple( |
| 33360 | } | 33379 | } |
| 33361 | | 33380 | |
| 33362 | fn getBuiltin(sema: *Sema, name: []const u8) CompileError!Air.Inst.Ref { | 33381 | fn getBuiltin(sema: *Sema, name: []const u8) CompileError!Air.Inst.Ref { |
| 33363 | var wip_captures = try WipCaptureScope.init(sema.gpa, sema.perm_arena, sema.owner_decl.src_scope); | 33382 | var wip_captures = try WipCaptureScope.init(sema.gpa, sema.owner_decl.src_scope); |
| 33364 | defer wip_captures.deinit(); | 33383 | defer wip_captures.deinit(); |
| 33365 | | 33384 | |
| 33366 | var block: Block = .{ | 33385 | var block: Block = .{ |
| ... | @@ -33405,7 +33424,7 @@ fn getBuiltin(sema: *Sema, name: []const u8) CompileError!Air.Inst.Ref { | ... | @@ -33405,7 +33424,7 @@ fn getBuiltin(sema: *Sema, name: []const u8) CompileError!Air.Inst.Ref { |
| 33405 | fn getBuiltinType(sema: *Sema, name: []const u8) CompileError!Type { | 33424 | fn getBuiltinType(sema: *Sema, name: []const u8) CompileError!Type { |
| 33406 | const ty_inst = try sema.getBuiltin(name); | 33425 | const ty_inst = try sema.getBuiltin(name); |
| 33407 | | 33426 | |
| 33408 | var wip_captures = try WipCaptureScope.init(sema.gpa, sema.perm_arena, sema.owner_decl.src_scope); | 33427 | var wip_captures = try WipCaptureScope.init(sema.gpa, sema.owner_decl.src_scope); |
| 33409 | defer wip_captures.deinit(); | 33428 | defer wip_captures.deinit(); |
| 33410 | | 33429 | |
| 33411 | var block: Block = .{ | 33430 | var block: Block = .{ |