authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2022-10-30 15:09:45-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2022-10-30 15:25:58-04:00
log5c3a486639443e2fa62433b95108d956088e73bd
tree0ea16023d32ebd5bdbe908e6a424e62b19d094c2
parent8caed4846018cd185b632bc884c7df81b8dd39dc

AstGen: avoid accessing value from inner scope

While continue expressions can access the capture, so ensure that it is unwrapped in an outer scope.

1 files changed, 37 insertions(+), 33 deletions(-)

src/AstGen.zig+37-33
...@@ -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);
59125912
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();
59155915
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] == .asterisk5917 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 };
59505950
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_scope5956 // 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);
59585958
5959 // make scope now but don't stack on parent_gz until loop_scope5959 // make scope now but don't stack on parent_gz until loop_scope
5960 // gets unstacked after cont_expr is emitted and added below5960 // 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();
59645964
...@@ -6026,24 +6026,17 @@ fn whileExpr(...@@ -6026,24 +6026,17 @@ fn whileExpr(
6026 }6026 }
6027 };6027 };
60286028
6029 // This code could be improved to avoid emitting the continue expr when there6029 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 noreturn6030 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/91856032 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);
60436036
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_scope6047 // 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;
60566049
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);
60646062
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);
60676072
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();
60706075
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,