| ... | @@ -1864,15 +1864,8 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn | ... | @@ -1864,15 +1864,8 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn |
| 1864 | } | 1864 | } |
| 1865 | block_gz.break_count += 1; | 1865 | block_gz.break_count += 1; |
| 1866 | | 1866 | |
| 1867 | // The loop scope has a mechanism to prevent rvalue() from emitting a | | |
| 1868 | // store to the result location for the loop body (since it is continues | | |
| 1869 | // rather than returning a result from the loop) but here is a `break` | | |
| 1870 | // which needs to override this behavior. | | |
| 1871 | const prev_rvalue_noresult = parent_gz.rvalue_noresult; | | |
| 1872 | parent_gz.rvalue_noresult = .none; | | |
| 1873 | const operand = try reachableExpr(parent_gz, parent_scope, block_gz.break_result_loc, rhs, node); | 1867 | const operand = try reachableExpr(parent_gz, parent_scope, block_gz.break_result_loc, rhs, node); |
| 1874 | const search_index = @intCast(Zir.Inst.Index, astgen.instructions.len); | 1868 | const search_index = @intCast(Zir.Inst.Index, astgen.instructions.len); |
| 1875 | parent_gz.rvalue_noresult = prev_rvalue_noresult; | | |
| 1876 | | 1869 | |
| 1877 | try genDefers(parent_gz, scope, parent_scope, .normal_only); | 1870 | try genDefers(parent_gz, scope, parent_scope, .normal_only); |
| 1878 | | 1871 | |
| ... | @@ -2193,7 +2186,7 @@ fn blockExprStmts(gz: *GenZir, parent_scope: *Scope, statements: []const Ast.Nod | ... | @@ -2193,7 +2186,7 @@ fn blockExprStmts(gz: *GenZir, parent_scope: *Scope, statements: []const Ast.Nod |
| 2193 | .assign_add_wrap => try assignOp(gz, scope, statement, .addwrap), | 2186 | .assign_add_wrap => try assignOp(gz, scope, statement, .addwrap), |
| 2194 | .assign_mul => try assignOp(gz, scope, statement, .mul), | 2187 | .assign_mul => try assignOp(gz, scope, statement, .mul), |
| 2195 | .assign_mul_wrap => try assignOp(gz, scope, statement, .mulwrap), | 2188 | .assign_mul_wrap => try assignOp(gz, scope, statement, .mulwrap), |
| 2196 | | 2189 | |
| 2197 | .grouped_expression => { | 2190 | .grouped_expression => { |
| 2198 | inner_node = node_data[statement].lhs; | 2191 | inner_node = node_data[statement].lhs; |
| 2199 | continue; | 2192 | continue; |
| ... | @@ -5789,7 +5782,6 @@ fn whileExpr( | ... | @@ -5789,7 +5782,6 @@ fn whileExpr( |
| 5789 | // make scope now but don't stack on parent_gz until loop_scope | 5782 | // make scope now but don't stack on parent_gz until loop_scope |
| 5790 | // gets unstacked after cont_expr is emitted and added below | 5783 | // gets unstacked after cont_expr is emitted and added below |
| 5791 | var then_scope = parent_gz.makeSubBlock(&continue_scope.base); | 5784 | var then_scope = parent_gz.makeSubBlock(&continue_scope.base); |
| 5792 | then_scope.markAsLoopBody(loop_scope); | | |
| 5793 | then_scope.instructions_top = GenZir.unstacked_top; | 5785 | then_scope.instructions_top = GenZir.unstacked_top; |
| 5794 | defer then_scope.unstack(); | 5786 | defer then_scope.unstack(); |
| 5795 | | 5787 | |
| ... | @@ -5889,7 +5881,7 @@ fn whileExpr( | ... | @@ -5889,7 +5881,7 @@ fn whileExpr( |
| 5889 | if (dbg_var_name) |some| { | 5881 | if (dbg_var_name) |some| { |
| 5890 | try then_scope.addDbgVar(.dbg_var_val, some, dbg_var_inst); | 5882 | try then_scope.addDbgVar(.dbg_var_val, some, dbg_var_inst); |
| 5891 | } | 5883 | } |
| 5892 | const then_result = try expr(&then_scope, then_sub_scope, loop_scope.break_result_loc, while_full.ast.then_expr); | 5884 | const then_result = try expr(&then_scope, then_sub_scope, .none, while_full.ast.then_expr); |
| 5893 | _ = try addEnsureResult(&then_scope, then_result, while_full.ast.then_expr); | 5885 | _ = try addEnsureResult(&then_scope, then_result, while_full.ast.then_expr); |
| 5894 | | 5886 | |
| 5895 | try checkUsed(parent_gz, &then_scope.base, then_sub_scope); | 5887 | try checkUsed(parent_gz, &then_scope.base, then_sub_scope); |
| ... | @@ -6067,7 +6059,6 @@ fn forExpr( | ... | @@ -6067,7 +6059,6 @@ fn forExpr( |
| 6067 | } | 6059 | } |
| 6068 | | 6060 | |
| 6069 | var then_scope = parent_gz.makeSubBlock(&cond_scope.base); | 6061 | var then_scope = parent_gz.makeSubBlock(&cond_scope.base); |
| 6070 | then_scope.markAsLoopBody(loop_scope); | | |
| 6071 | defer then_scope.unstack(); | 6062 | defer then_scope.unstack(); |
| 6072 | | 6063 | |
| 6073 | try then_scope.addDbgBlockBegin(); | 6064 | try then_scope.addDbgBlockBegin(); |
| ... | @@ -6129,7 +6120,7 @@ fn forExpr( | ... | @@ -6129,7 +6120,7 @@ fn forExpr( |
| 6129 | break :blk &index_scope.base; | 6120 | break :blk &index_scope.base; |
| 6130 | }; | 6121 | }; |
| 6131 | | 6122 | |
| 6132 | const then_result = try expr(&then_scope, then_sub_scope, loop_scope.break_result_loc, for_full.ast.then_expr); | 6123 | const then_result = try expr(&then_scope, then_sub_scope, .none, for_full.ast.then_expr); |
| 6133 | _ = try addEnsureResult(&then_scope, then_result, for_full.ast.then_expr); | 6124 | _ = try addEnsureResult(&then_scope, then_result, for_full.ast.then_expr); |
| 6134 | | 6125 | |
| 6135 | try checkUsed(parent_gz, &then_scope.base, then_sub_scope); | 6126 | try checkUsed(parent_gz, &then_scope.base, then_sub_scope); |
| ... | @@ -9465,25 +9456,19 @@ fn rvalue( | ... | @@ -9465,25 +9456,19 @@ fn rvalue( |
| 9465 | } | 9456 | } |
| 9466 | }, | 9457 | }, |
| 9467 | .ptr => |ptr_inst| { | 9458 | .ptr => |ptr_inst| { |
| 9468 | if (gz.rvalue_noresult != ptr_inst) { | 9459 | _ = try gz.addPlNode(.store_node, src_node, Zir.Inst.Bin{ |
| 9469 | _ = try gz.addPlNode(.store_node, src_node, Zir.Inst.Bin{ | 9460 | .lhs = ptr_inst, |
| 9470 | .lhs = ptr_inst, | 9461 | .rhs = result, |
| 9471 | .rhs = result, | 9462 | }); |
| 9472 | }); | | |
| 9473 | } | | |
| 9474 | return result; | 9463 | return result; |
| 9475 | }, | 9464 | }, |
| 9476 | .inferred_ptr => |alloc| { | 9465 | .inferred_ptr => |alloc| { |
| 9477 | if (gz.rvalue_noresult != alloc) { | 9466 | _ = try gz.addBin(.store_to_inferred_ptr, alloc, result); |
| 9478 | _ = try gz.addBin(.store_to_inferred_ptr, alloc, result); | | |
| 9479 | } | | |
| 9480 | return result; | 9467 | return result; |
| 9481 | }, | 9468 | }, |
| 9482 | .block_ptr => |block_scope| { | 9469 | .block_ptr => |block_scope| { |
| 9483 | if (gz.rvalue_noresult != block_scope.rl_ptr) { | 9470 | block_scope.rvalue_rl_count += 1; |
| 9484 | block_scope.rvalue_rl_count += 1; | 9471 | _ = try gz.addBin(.store_to_block_ptr, block_scope.rl_ptr, result); |
| 9485 | _ = try gz.addBin(.store_to_block_ptr, block_scope.rl_ptr, result); | | |
| 9486 | } | | |
| 9487 | return result; | 9472 | return result; |
| 9488 | }, | 9473 | }, |
| 9489 | } | 9474 | } |
| ... | @@ -10163,7 +10148,6 @@ const GenZir = struct { | ... | @@ -10163,7 +10148,6 @@ const GenZir = struct { |
| 10163 | rl_ptr: Zir.Inst.Ref = .none, | 10148 | rl_ptr: Zir.Inst.Ref = .none, |
| 10164 | /// When a block has a type result location, here it is. | 10149 | /// When a block has a type result location, here it is. |
| 10165 | rl_ty_inst: Zir.Inst.Ref = .none, | 10150 | rl_ty_inst: Zir.Inst.Ref = .none, |
| 10166 | rvalue_noresult: Zir.Inst.Ref = .none, | | |
| 10167 | /// Keeps track of how many branches of a block did not actually | 10151 | /// Keeps track of how many branches of a block did not actually |
| 10168 | /// consume the result location. astgen uses this to figure out | 10152 | /// consume the result location. astgen uses this to figure out |
| 10169 | /// whether to rely on break instructions or writing to the result | 10153 | /// whether to rely on break instructions or writing to the result |
| ... | @@ -11558,17 +11542,6 @@ const GenZir = struct { | ... | @@ -11558,17 +11542,6 @@ const GenZir = struct { |
| 11558 | try gz.astgen.instructions.append(gpa, .{ .tag = .dbg_block_end, .data = undefined }); | 11542 | try gz.astgen.instructions.append(gpa, .{ .tag = .dbg_block_end, .data = undefined }); |
| 11559 | try gz.instructions.insert(gpa, gz.instructions.items.len - 1, new_index); | 11543 | try gz.instructions.insert(gpa, gz.instructions.items.len - 1, new_index); |
| 11560 | } | 11544 | } |
| 11561 | | | |
| 11562 | /// Control flow does not fall through the "then" block of a loop; it continues | | |
| 11563 | /// back to the while condition. This prevents `rvalue` from | | |
| 11564 | /// adding an invalid store to the result location of `then_scope`. | | |
| 11565 | fn markAsLoopBody(gz: *GenZir, loop_scope: GenZir) void { | | |
| 11566 | gz.rvalue_noresult = switch (loop_scope.break_result_loc) { | | |
| 11567 | .ptr, .inferred_ptr => |ptr| ptr, | | |
| 11568 | .block_ptr => |block| block.rl_ptr, | | |
| 11569 | else => .none, | | |
| 11570 | }; | | |
| 11571 | } | | |
| 11572 | }; | 11545 | }; |
| 11573 | | 11546 | |
| 11574 | /// This can only be for short-lived references; the memory becomes invalidated | 11547 | /// This can only be for short-lived references; the memory becomes invalidated |