authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-09-09 16:44:23-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-09-09 16:44:23-04:00
log852679c3695af19f218fdc9eab22c6fdf8d09622
tree3a77eec40dec41edb707536e630de6e62e2948d7
parenta3993465feefae6e64f16ce7e7a70251a739cb22
signaturelock-open Commit is signed but in an unrecognized format.

fix a var decl in scope preventing for loop spills


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

src/analyze.cpp+9-2
...@@ -5701,23 +5701,30 @@ static ZigType *get_async_fn_type(CodeGen *g, ZigType *orig_fn_type) {...@@ -5701,23 +5701,30 @@ static ZigType *get_async_fn_type(CodeGen *g, ZigType *orig_fn_type) {
5701// (await y) + x5701// (await y) + x
5702static void mark_suspension_point(Scope *scope) {5702static void mark_suspension_point(Scope *scope) {
5703 ScopeExpr *child_expr_scope = (scope->id == ScopeIdExpr) ? reinterpret_cast<ScopeExpr *>(scope) : nullptr;5703 ScopeExpr *child_expr_scope = (scope->id == ScopeIdExpr) ? reinterpret_cast<ScopeExpr *>(scope) : nullptr;
5704 bool looking_for_exprs = true;
5704 for (;;) {5705 for (;;) {
5705 scope = scope->parent;5706 scope = scope->parent;
5706 switch (scope->id) {5707 switch (scope->id) {
5707 case ScopeIdDefer:
5708 case ScopeIdDeferExpr:5708 case ScopeIdDeferExpr:
5709 case ScopeIdDecls:5709 case ScopeIdDecls:
5710 case ScopeIdFnDef:5710 case ScopeIdFnDef:
5711 case ScopeIdCompTime:5711 case ScopeIdCompTime:
5712 case ScopeIdVarDecl:
5713 case ScopeIdCImport:5712 case ScopeIdCImport:
5714 case ScopeIdSuspend:5713 case ScopeIdSuspend:
5715 case ScopeIdTypeOf:5714 case ScopeIdTypeOf:
5716 return;5715 return;
5716 case ScopeIdVarDecl:
5717 case ScopeIdDefer:
5718 looking_for_exprs = false;
5719 continue;
5717 case ScopeIdLoop:5720 case ScopeIdLoop:
5718 case ScopeIdRuntime:5721 case ScopeIdRuntime:
5719 continue;5722 continue;
5720 case ScopeIdExpr: {5723 case ScopeIdExpr: {
5724 if (!looking_for_exprs) {
5725 // Now we're only looking for a block, to see if it's in a loop (see the case ScopeIdBlock)
5726 continue;
5727 }
5721 ScopeExpr *parent_expr_scope = reinterpret_cast<ScopeExpr *>(scope);5728 ScopeExpr *parent_expr_scope = reinterpret_cast<ScopeExpr *>(scope);
5722 if (child_expr_scope != nullptr) {5729 if (child_expr_scope != nullptr) {
5723 for (size_t i = 0; parent_expr_scope->children_ptr[i] != child_expr_scope; i += 1) {5730 for (size_t i = 0; parent_expr_scope->children_ptr[i] != child_expr_scope; i += 1) {
test/stage1/behavior/async_fn.zig+35
...@@ -1233,3 +1233,38 @@ test "spill target expr in a for loop" {...@@ -1233,3 +1233,38 @@ test "spill target expr in a for loop" {
1233 resume S.global_frame;1233 resume S.global_frame;
1234}1234}
12351235
1236test "spill target expr in a for loop, with a var decl in the loop body" {
1237 const S = struct {
1238 var global_frame: anyframe = undefined;
1239
1240 fn doTheTest() void {
1241 var foo = Foo{
1242 .slice = [_]i32{1, 2},
1243 };
1244 expect(atest(&foo) == 3);
1245 }
1246
1247 const Foo = struct {
1248 slice: []i32,
1249 };
1250
1251 fn atest(foo: *Foo) i32 {
1252 var sum: i32 = 0;
1253 for (foo.slice) |x| {
1254 // Previously this var decl would prevent spills. This test makes sure
1255 // the for loop spills still happen even though there is a VarDecl in scope
1256 // before the suspend.
1257 var anything = true;
1258 _ = anything;
1259 suspend {
1260 global_frame = @frame();
1261 }
1262 sum += x;
1263 }
1264 return sum;
1265 }
1266 };
1267 _ = async S.doTheTest();
1268 resume S.global_frame;
1269 resume S.global_frame;
1270}