| ... | ... | @@ -5910,8 +5910,8 @@ fn whileExpr( |
| 5910 | 5910 | defer loop_scope.unstack(); |
| 5911 | 5911 | defer loop_scope.labeled_breaks.deinit(astgen.gpa); |
| 5912 | 5912 | |
| 5913 | | var continue_scope = parent_gz.makeSubBlock(&loop_scope.base); |
| 5914 | | defer continue_scope.unstack(); |
| 5913 | var cond_scope = parent_gz.makeSubBlock(&loop_scope.base); |
| 5914 | defer cond_scope.unstack(); |
| 5915 | 5915 | |
| 5916 | 5916 | const payload_is_ref = if (while_full.payload_token) |payload_token| |
| 5917 | 5917 | token_tags[payload_token] == .asterisk |
| ... | ... | @@ -5925,22 +5925,22 @@ fn whileExpr( |
| 5925 | 5925 | } = c: { |
| 5926 | 5926 | if (while_full.error_token) |_| { |
| 5927 | 5927 | const cond_ri: ResultInfo = .{ .rl = if (payload_is_ref) .ref else .none }; |
| 5928 | | const err_union = try expr(&continue_scope, &continue_scope.base, cond_ri, while_full.ast.cond_expr); |
| 5928 | const err_union = try expr(&cond_scope, &cond_scope.base, cond_ri, while_full.ast.cond_expr); |
| 5929 | 5929 | const tag: Zir.Inst.Tag = if (payload_is_ref) .is_non_err_ptr else .is_non_err; |
| 5930 | 5930 | break :c .{ |
| 5931 | 5931 | .inst = err_union, |
| 5932 | | .bool_bit = try continue_scope.addUnNode(tag, err_union, while_full.ast.then_expr), |
| 5932 | .bool_bit = try cond_scope.addUnNode(tag, err_union, while_full.ast.then_expr), |
| 5933 | 5933 | }; |
| 5934 | 5934 | } else if (while_full.payload_token) |_| { |
| 5935 | 5935 | const cond_ri: ResultInfo = .{ .rl = if (payload_is_ref) .ref else .none }; |
| 5936 | | const optional = try expr(&continue_scope, &continue_scope.base, cond_ri, while_full.ast.cond_expr); |
| 5936 | const optional = try expr(&cond_scope, &cond_scope.base, cond_ri, while_full.ast.cond_expr); |
| 5937 | 5937 | const tag: Zir.Inst.Tag = if (payload_is_ref) .is_non_null_ptr else .is_non_null; |
| 5938 | 5938 | break :c .{ |
| 5939 | 5939 | .inst = optional, |
| 5940 | | .bool_bit = try continue_scope.addUnNode(tag, optional, while_full.ast.then_expr), |
| 5940 | .bool_bit = try cond_scope.addUnNode(tag, optional, while_full.ast.then_expr), |
| 5941 | 5941 | }; |
| 5942 | 5942 | } else { |
| 5943 | | const cond = try expr(&continue_scope, &continue_scope.base, bool_ri, while_full.ast.cond_expr); |
| 5943 | const cond = try expr(&cond_scope, &cond_scope.base, bool_ri, while_full.ast.cond_expr); |
| 5944 | 5944 | break :c .{ |
| 5945 | 5945 | .inst = cond, |
| 5946 | 5946 | .bool_bit = cond, |
| ... | ... | @@ -5949,16 +5949,16 @@ fn whileExpr( |
| 5949 | 5949 | }; |
| 5950 | 5950 | |
| 5951 | 5951 | const condbr_tag: Zir.Inst.Tag = if (is_inline) .condbr_inline else .condbr; |
| 5952 | | const condbr = try continue_scope.addCondBr(condbr_tag, node); |
| 5952 | const condbr = try cond_scope.addCondBr(condbr_tag, node); |
| 5953 | 5953 | const block_tag: Zir.Inst.Tag = if (is_inline) .block_inline else .block; |
| 5954 | 5954 | const cond_block = try loop_scope.makeBlockInst(block_tag, node); |
| 5955 | | try continue_scope.setBlockBody(cond_block); |
| 5956 | | // continue_scope unstacked now, can add new instructions to loop_scope |
| 5955 | try cond_scope.setBlockBody(cond_block); |
| 5956 | // cond_scope unstacked now, can add new instructions to loop_scope |
| 5957 | 5957 | try loop_scope.instructions.append(astgen.gpa, cond_block); |
| 5958 | 5958 | |
| 5959 | 5959 | // make scope now but don't stack on parent_gz until loop_scope |
| 5960 | 5960 | // gets unstacked after cont_expr is emitted and added below |
| 5961 | | var then_scope = parent_gz.makeSubBlock(&continue_scope.base); |
| 5961 | var then_scope = parent_gz.makeSubBlock(&cond_scope.base); |
| 5962 | 5962 | then_scope.instructions_top = GenZir.unstacked_top; |
| 5963 | 5963 | defer then_scope.unstack(); |
| 5964 | 5964 | |
| ... | ... | @@ -6026,24 +6026,17 @@ fn whileExpr( |
| 6026 | 6026 | } |
| 6027 | 6027 | }; |
| 6028 | 6028 | |
| 6029 | | // This code could be improved to avoid emitting the continue expr when there |
| 6030 | | // are no jumps to it. This happens when the last statement of a while body is noreturn |
| 6031 | | // and there are no `continue` statements. |
| 6032 | | // Tracking issue: https://github.com/ziglang/zig/issues/9185 |
| 6033 | | try then_scope.addDbgBlockBegin(); |
| 6034 | | if (dbg_var_name) |some| { |
| 6035 | | try then_scope.addDbgVar(.dbg_var_val, some, dbg_var_inst); |
| 6036 | | } |
| 6037 | | if (while_full.ast.cont_expr != 0) { |
| 6038 | | _ = try unusedResultExpr(&loop_scope, then_sub_scope, while_full.ast.cont_expr); |
| 6039 | | } |
| 6040 | | try then_scope.addDbgBlockEnd(); |
| 6029 | var continue_scope = parent_gz.makeSubBlock(then_sub_scope); |
| 6030 | continue_scope.instructions_top = GenZir.unstacked_top; |
| 6031 | defer continue_scope.unstack(); |
| 6032 | const continue_block = try then_scope.makeBlockInst(block_tag, node); |
| 6033 | |
| 6041 | 6034 | const repeat_tag: Zir.Inst.Tag = if (is_inline) .repeat_inline else .repeat; |
| 6042 | 6035 | _ = try loop_scope.addNode(repeat_tag, node); |
| 6043 | 6036 | |
| 6044 | 6037 | try loop_scope.setBlockBody(loop_block); |
| 6045 | 6038 | loop_scope.break_block = loop_block; |
| 6046 | | loop_scope.continue_block = cond_block; |
| 6039 | loop_scope.continue_block = continue_block; |
| 6047 | 6040 | if (while_full.label_token) |label_token| { |
| 6048 | 6041 | loop_scope.label = @as(?GenZir.Label, GenZir.Label{ |
| 6049 | 6042 | .token = label_token, |
| ... | ... | @@ -6054,18 +6047,30 @@ fn whileExpr( |
| 6054 | 6047 | // done adding instructions to loop_scope, can now stack then_scope |
| 6055 | 6048 | then_scope.instructions_top = then_scope.instructions.items.len; |
| 6056 | 6049 | |
| 6057 | | if (payload_inst != 0) try then_scope.instructions.append(astgen.gpa, payload_inst); |
| 6058 | 6050 | try then_scope.addDbgBlockBegin(); |
| 6059 | | if (dbg_var_name) |some| { |
| 6060 | | try then_scope.addDbgVar(.dbg_var_val, some, dbg_var_inst); |
| 6051 | if (payload_inst != 0) try then_scope.instructions.append(astgen.gpa, payload_inst); |
| 6052 | if (dbg_var_name) |name| try then_scope.addDbgVar(.dbg_var_val, name, dbg_var_inst); |
| 6053 | try then_scope.instructions.append(astgen.gpa, continue_block); |
| 6054 | // This code could be improved to avoid emitting the continue expr when there |
| 6055 | // are no jumps to it. This happens when the last statement of a while body is noreturn |
| 6056 | // and there are no `continue` statements. |
| 6057 | // Tracking issue: https://github.com/ziglang/zig/issues/9185 |
| 6058 | if (while_full.ast.cont_expr != 0) { |
| 6059 | _ = try unusedResultExpr(&then_scope, then_sub_scope, while_full.ast.cont_expr); |
| 6061 | 6060 | } |
| 6062 | | const then_result = try expr(&then_scope, then_sub_scope, .{ .rl = .none }, while_full.ast.then_expr); |
| 6063 | | _ = try addEnsureResult(&then_scope, then_result, while_full.ast.then_expr); |
| 6061 | try then_scope.addDbgBlockEnd(); |
| 6064 | 6062 | |
| 6063 | continue_scope.instructions_top = continue_scope.instructions.items.len; |
| 6064 | _ = try unusedResultExpr(&continue_scope, &continue_scope.base, while_full.ast.then_expr); |
| 6065 | 6065 | try checkUsed(parent_gz, &then_scope.base, then_sub_scope); |
| 6066 | | try then_scope.addDbgBlockEnd(); |
| 6066 | const break_tag: Zir.Inst.Tag = if (is_inline) .break_inline else .@"break"; |
| 6067 | if (!continue_scope.endsWithNoReturn()) { |
| 6068 | const break_inst = try continue_scope.makeBreak(break_tag, continue_block, .void_value); |
| 6069 | try then_scope.instructions.append(astgen.gpa, break_inst); |
| 6070 | } |
| 6071 | try continue_scope.setBlockBody(continue_block); |
| 6067 | 6072 | |
| 6068 | | var else_scope = parent_gz.makeSubBlock(&continue_scope.base); |
| 6073 | var else_scope = parent_gz.makeSubBlock(&cond_scope.base); |
| 6069 | 6074 | defer else_scope.unstack(); |
| 6070 | 6075 | |
| 6071 | 6076 | const else_node = while_full.ast.else_expr; |
| ... | ... | @@ -6128,7 +6133,6 @@ fn whileExpr( |
| 6128 | 6133 | try astgen.appendErrorTok(some.token, "unused while loop label", .{}); |
| 6129 | 6134 | } |
| 6130 | 6135 | } |
| 6131 | | const break_tag: Zir.Inst.Tag = if (is_inline) .break_inline else .@"break"; |
| 6132 | 6136 | const result = try finishThenElseBlock( |
| 6133 | 6137 | parent_gz, |
| 6134 | 6138 | ri, |
| ... | ... | @@ -6138,7 +6142,7 @@ fn whileExpr( |
| 6138 | 6142 | &else_scope, |
| 6139 | 6143 | condbr, |
| 6140 | 6144 | cond.bool_bit, |
| 6141 | | then_result, |
| 6145 | .void_value, |
| 6142 | 6146 | else_info.result, |
| 6143 | 6147 | loop_block, |
| 6144 | 6148 | cond_block, |