This is an archive of the discontinued LLVM Phabricator instance.

[Coroutines] Avoid creating conditional cleanup markers in suspend block
ClosedPublic

Authored by weiwang on Feb 23 2023, 3:00 PM.

Details

Summary

We shouldn't access coro frame after returning from await_suspend() and before llvm.coro.suspend().
Make sure we always hoist conditional cleanup markers when inside the await.suspend block.

Fix https://github.com/llvm/llvm-project/issues/59181

Diff Detail

Event Timeline

weiwang created this revision.Feb 23 2023, 3:00 PM
Herald added a project: Restricted Project. · View Herald TranscriptFeb 23 2023, 3:00 PM
weiwang requested review of this revision.Feb 23 2023, 3:00 PM
Herald added a project: Restricted Project. · View Herald TranscriptFeb 23 2023, 3:00 PM
Herald added a subscriber: cfe-commits. · View Herald Transcript
weiwang edited the summary of this revision. (Show Details)Feb 23 2023, 3:13 PM
weiwang added a reviewer: ChuanqiXu.
weiwang edited the summary of this revision. (Show Details)Feb 23 2023, 3:17 PM
weiwang added a reviewer: bruno.
bruno added a comment.Feb 23 2023, 3:29 PM

Thanks for working on this Wei!

Can you please add a testcase?

clang/lib/CodeGen/CodeGenFunction.h
336

Should this live inside CGCoroData instead?

The test should be required here.

clang/lib/CodeGen/CGExpr.cpp
544–547

We should add comment to explain why we add a forward path for coroutines.

BTW, what is the conclusion for the concern about sanitizers? Would change make sanitizers to perform false positive diagnostics?

BTW, what is the conclusion for the concern about sanitizers? Would change make sanitizers to perform false positive diagnostics?

This change is limited to the await.suspend block, which only does codegen for awaiter.await_suspend(coroutine_handle<p>::from_promise(p)). In this case, I think the only asan check removed by the change is the conditional marker for cleanup the temporary coroutine_handler used as the parameter of await_suspend, so my understanding is that it shouldn't affect asan diagnostic.

To show the difference it makes to the source from issue #59181

Before:

%ref.tmp25 = alloca %"struct.std::__1::coroutine_handle.6", align 8
...
// asan check inserted here
bool cond_cleanup_marker = false;

if (cond) {
    // get awaiter
    ...

    if (!awaiter.await_ready()) {
        call void @llvm.lifetime.start.p0(i64 8, ptr %ref.tmp25)
        
        // asan check inserted here
	cond_cleanup_marker = true;
	
        // store handler to %ref.tmp25
	...
	
        awaiter.await_suspend();

        // asan check inserted here
	if (cond_cleanup_marker)
	    call void @llvm.lifetime.end.p0(i64 8, ptr %ref.tmp25)
        call i8 @llvm.coro.suspend(...)
	...
    }
    ...
} else {
    ... 
}
...
lpad:
    ...
    // asan check inserted here
    if (cond_cleanup_marker)
        call void @llvm.lifetime.end.p0(i64 8, ptr %ref.tmp25)

The issue is only reproduced in -O0, because `cond_cleanup_marker is optimized away in -O1 or up opt level.

After:

%ref.tmp25 = alloca %"struct.std::__1::coroutine_handle.6", align 8
...

call void @llvm.lifetime.start.p0(i64 8, ptr %ref.tmp25)

if (cond) {
    ...
    if (!awaiter.await_ready()) {
        // store handler to %ref.tmp25
	...

	awaiter.await_suspend();
	call void @llvm.lifetime.end.p0(i64 8, ptr %ref.tmp25)
	call i8 @llvm.coro.suspend(...)
	...
    }
    ...
} else {
    ... 
}
...
lpad:
    call void @llvm.lifetime.end.p0(i64 8, ptr %ref.tmp25)

This also matches with the IR without asan.

clang/lib/CodeGen/CGExpr.cpp
544–547

Will do

clang/lib/CodeGen/CodeGenFunction.h
336

CGCoroData is forward declared here, so it does not know what's inside.

weiwang updated this revision to Diff 500958.Feb 27 2023, 4:16 PM
weiwang edited the summary of this revision. (Show Details)

add test case and some comments

ChuanqiXu accepted this revision.Feb 27 2023, 6:29 PM

LGTM, then.

This revision is now accepted and ready to land.Feb 27 2023, 6:29 PM
weiwang updated this revision to Diff 501205.Feb 28 2023, 10:14 AM

add target triple

This revision was landed with ongoing or failed builds.Feb 28 2023, 3:31 PM
This revision was automatically updated to reflect the committed changes.