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