fix a var decl in scope preventing for loop spills

This commit is contained in:
Andrew Kelley 2019-09-09 16:44:23 -04:00
parent a3993465fe
commit 852679c369
No known key found for this signature in database
GPG Key ID: 7C5F548F728501A9
2 changed files with 44 additions and 2 deletions

View File

@ -5701,23 +5701,30 @@ static ZigType *get_async_fn_type(CodeGen *g, ZigType *orig_fn_type) {
// (await y) + x
static void mark_suspension_point(Scope *scope) {
ScopeExpr *child_expr_scope = (scope->id == ScopeIdExpr) ? reinterpret_cast<ScopeExpr *>(scope) : nullptr;
bool looking_for_exprs = true;
for (;;) {
scope = scope->parent;
switch (scope->id) {
case ScopeIdDefer:
case ScopeIdDeferExpr:
case ScopeIdDecls:
case ScopeIdFnDef:
case ScopeIdCompTime:
case ScopeIdVarDecl:
case ScopeIdCImport:
case ScopeIdSuspend:
case ScopeIdTypeOf:
return;
case ScopeIdVarDecl:
case ScopeIdDefer:
looking_for_exprs = false;
continue;
case ScopeIdLoop:
case ScopeIdRuntime:
continue;
case ScopeIdExpr: {
if (!looking_for_exprs) {
// Now we're only looking for a block, to see if it's in a loop (see the case ScopeIdBlock)
continue;
}
ScopeExpr *parent_expr_scope = reinterpret_cast<ScopeExpr *>(scope);
if (child_expr_scope != nullptr) {
for (size_t i = 0; parent_expr_scope->children_ptr[i] != child_expr_scope; i += 1) {

View File

@ -1233,3 +1233,38 @@ test "spill target expr in a for loop" {
resume S.global_frame;
}
test "spill target expr in a for loop, with a var decl in the loop body" {
const S = struct {
var global_frame: anyframe = undefined;
fn doTheTest() void {
var foo = Foo{
.slice = [_]i32{1, 2},
};
expect(atest(&foo) == 3);
}
const Foo = struct {
slice: []i32,
};
fn atest(foo: *Foo) i32 {
var sum: i32 = 0;
for (foo.slice) |x| {
// Previously this var decl would prevent spills. This test makes sure
// the for loop spills still happen even though there is a VarDecl in scope
// before the suspend.
var anything = true;
_ = anything;
suspend {
global_frame = @frame();
}
sum += x;
}
return sum;
}
};
_ = async S.doTheTest();
resume S.global_frame;
resume S.global_frame;
}