authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-01-29 13:37:58-05:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2020-01-29 13:37:58-05:00
log4fad16284ec30962689723c7eaca05a77df14673
tree9972dea0bfea56c23aacf3ffe7afa6f110a2f009
parent34706dad3ff22f73197fbf5e9cbf4628f698a74d
parent9a0a378e2f957f6acf5fbb37818d1cc0e3a38d33
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #4320 from fengb/while-spills

Add async spills to while captured variables

2 files changed, 44 insertions(+), 4 deletions(-)

src/ir.cpp+8-4
...@@ -8111,6 +8111,7 @@ static IrInstSrc *ir_gen_while_expr(IrBuilderSrc *irb, Scope *scope, AstNode *no...@@ -8111,6 +8111,7 @@ static IrInstSrc *ir_gen_while_expr(IrBuilderSrc *irb, Scope *scope, AstNode *no
8111 } else {8111 } else {
8112 payload_scope = subexpr_scope;8112 payload_scope = subexpr_scope;
8113 }8113 }
8114 ScopeExpr *spill_scope = create_expr_scope(irb->codegen, node, payload_scope);
8114 IrInstSrc *err_val_ptr = ir_gen_node_extra(irb, node->data.while_expr.condition, subexpr_scope,8115 IrInstSrc *err_val_ptr = ir_gen_node_extra(irb, node->data.while_expr.condition, subexpr_scope,
8115 LValPtr, nullptr);8116 LValPtr, nullptr);
8116 if (err_val_ptr == irb->codegen->invalid_inst_src)8117 if (err_val_ptr == irb->codegen->invalid_inst_src)
...@@ -8134,10 +8135,10 @@ static IrInstSrc *ir_gen_while_expr(IrBuilderSrc *irb, Scope *scope, AstNode *no...@@ -8134,10 +8135,10 @@ static IrInstSrc *ir_gen_while_expr(IrBuilderSrc *irb, Scope *scope, AstNode *no
81348135
8135 ir_set_cursor_at_end_and_append_block(irb, body_block);8136 ir_set_cursor_at_end_and_append_block(irb, body_block);
8136 if (var_symbol) {8137 if (var_symbol) {
8137 IrInstSrc *payload_ptr = ir_build_unwrap_err_payload_src(irb, payload_scope, symbol_node,8138 IrInstSrc *payload_ptr = ir_build_unwrap_err_payload_src(irb, &spill_scope->base, symbol_node,
8138 err_val_ptr, false, false);8139 err_val_ptr, false, false);
8139 IrInstSrc *var_ptr = node->data.while_expr.var_is_ptr ?8140 IrInstSrc *var_ptr = node->data.while_expr.var_is_ptr ?
8140 ir_build_ref_src(irb, payload_scope, symbol_node, payload_ptr, true, false) : payload_ptr;8141 ir_build_ref_src(irb, &spill_scope->base, symbol_node, payload_ptr, true, false) : payload_ptr;
8141 ir_build_var_decl_src(irb, payload_scope, symbol_node, payload_var, nullptr, var_ptr);8142 ir_build_var_decl_src(irb, payload_scope, symbol_node, payload_var, nullptr, var_ptr);
8142 }8143 }
81438144
...@@ -8152,6 +8153,7 @@ static IrInstSrc *ir_gen_while_expr(IrBuilderSrc *irb, Scope *scope, AstNode *no...@@ -8152,6 +8153,7 @@ static IrInstSrc *ir_gen_while_expr(IrBuilderSrc *irb, Scope *scope, AstNode *no
8152 loop_scope->incoming_values = &incoming_values;8153 loop_scope->incoming_values = &incoming_values;
8153 loop_scope->lval = lval;8154 loop_scope->lval = lval;
8154 loop_scope->peer_parent = peer_parent;8155 loop_scope->peer_parent = peer_parent;
8156 loop_scope->spill_scope = spill_scope;
81558157
8156 // Note the body block of the loop is not the place that lval and result_loc are used -8158 // Note the body block of the loop is not the place that lval and result_loc are used -
8157 // it's actually in break statements, handled similarly to return statements.8159 // it's actually in break statements, handled similarly to return statements.
...@@ -8222,6 +8224,7 @@ static IrInstSrc *ir_gen_while_expr(IrBuilderSrc *irb, Scope *scope, AstNode *no...@@ -8222,6 +8224,7 @@ static IrInstSrc *ir_gen_while_expr(IrBuilderSrc *irb, Scope *scope, AstNode *no
8222 ZigVar *payload_var = ir_create_var(irb, symbol_node, subexpr_scope, var_symbol,8224 ZigVar *payload_var = ir_create_var(irb, symbol_node, subexpr_scope, var_symbol,
8223 true, false, false, is_comptime);8225 true, false, false, is_comptime);
8224 Scope *child_scope = payload_var->child_scope;8226 Scope *child_scope = payload_var->child_scope;
8227 ScopeExpr *spill_scope = create_expr_scope(irb->codegen, node, child_scope);
8225 IrInstSrc *maybe_val_ptr = ir_gen_node_extra(irb, node->data.while_expr.condition, subexpr_scope,8228 IrInstSrc *maybe_val_ptr = ir_gen_node_extra(irb, node->data.while_expr.condition, subexpr_scope,
8226 LValPtr, nullptr);8229 LValPtr, nullptr);
8227 if (maybe_val_ptr == irb->codegen->invalid_inst_src)8230 if (maybe_val_ptr == irb->codegen->invalid_inst_src)
...@@ -8244,9 +8247,9 @@ static IrInstSrc *ir_gen_while_expr(IrBuilderSrc *irb, Scope *scope, AstNode *no...@@ -8244,9 +8247,9 @@ static IrInstSrc *ir_gen_while_expr(IrBuilderSrc *irb, Scope *scope, AstNode *no
8244 is_comptime);8247 is_comptime);
82458248
8246 ir_set_cursor_at_end_and_append_block(irb, body_block);8249 ir_set_cursor_at_end_and_append_block(irb, body_block);
8247 IrInstSrc *payload_ptr = ir_build_optional_unwrap_ptr(irb, child_scope, symbol_node, maybe_val_ptr, false, false);8250 IrInstSrc *payload_ptr = ir_build_optional_unwrap_ptr(irb, &spill_scope->base, symbol_node, maybe_val_ptr, false, false);
8248 IrInstSrc *var_ptr = node->data.while_expr.var_is_ptr ?8251 IrInstSrc *var_ptr = node->data.while_expr.var_is_ptr ?
8249 ir_build_ref_src(irb, child_scope, symbol_node, payload_ptr, true, false) : payload_ptr;8252 ir_build_ref_src(irb, &spill_scope->base, symbol_node, payload_ptr, true, false) : payload_ptr;
8250 ir_build_var_decl_src(irb, child_scope, symbol_node, payload_var, nullptr, var_ptr);8253 ir_build_var_decl_src(irb, child_scope, symbol_node, payload_var, nullptr, var_ptr);
82518254
8252 ZigList<IrInstSrc *> incoming_values = {0};8255 ZigList<IrInstSrc *> incoming_values = {0};
...@@ -8260,6 +8263,7 @@ static IrInstSrc *ir_gen_while_expr(IrBuilderSrc *irb, Scope *scope, AstNode *no...@@ -8260,6 +8263,7 @@ static IrInstSrc *ir_gen_while_expr(IrBuilderSrc *irb, Scope *scope, AstNode *no
8260 loop_scope->incoming_values = &incoming_values;8263 loop_scope->incoming_values = &incoming_values;
8261 loop_scope->lval = lval;8264 loop_scope->lval = lval;
8262 loop_scope->peer_parent = peer_parent;8265 loop_scope->peer_parent = peer_parent;
8266 loop_scope->spill_scope = spill_scope;
82638267
8264 // Note the body block of the loop is not the place that lval and result_loc are used -8268 // Note the body block of the loop is not the place that lval and result_loc are used -
8265 // it's actually in break statements, handled similarly to return statements.8269 // it's actually in break statements, handled similarly to return statements.
test/stage1/behavior/async_fn.zig+36
...@@ -1182,6 +1182,42 @@ test "suspend in for loop" {...@@ -1182,6 +1182,42 @@ test "suspend in for loop" {
1182 S.doTheTest();1182 S.doTheTest();
1183}1183}
11841184
1185test "suspend in while loop" {
1186 const S = struct {
1187 var global_frame: ?anyframe = null;
1188
1189 fn doTheTest() void {
1190 _ = async atest();
1191 while (global_frame) |f| resume f;
1192 }
1193
1194 fn atest() void {
1195 expect(optional(6) == 6);
1196 expect(errunion(6) == 6);
1197 }
1198 fn optional(stuff: ?u32) u32 {
1199 global_frame = @frame();
1200 defer global_frame = null;
1201 while (stuff) |val| {
1202 suspend;
1203 return val;
1204 }
1205 return 0;
1206 }
1207 fn errunion(stuff: anyerror!u32) u32 {
1208 global_frame = @frame();
1209 defer global_frame = null;
1210 while (stuff) |val| {
1211 suspend;
1212 return val;
1213 } else |err| {
1214 return 0;
1215 }
1216 }
1217 };
1218 S.doTheTest();
1219}
1220
1185test "correctly spill when returning the error union result of another async fn" {1221test "correctly spill when returning the error union result of another async fn" {
1186 const S = struct {1222 const S = struct {
1187 var global_frame: anyframe = undefined;1223 var global_frame: anyframe = undefined;