Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 17 additions & 23 deletions CoroutinesCodeGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,6 @@ class CoroutineASTTransformer : public StmtVisitor<CoroutineASTTransformer>
CoroutineASTData& mASTData;
Stmt* mStaged{};
bool mSkip{};
bool mFinalSuspend{};
size_t& mSuspendsCount;
llvm::DenseMap<VarDecl*, MemberExpr*> mVarNamePrefix{};

Expand Down Expand Up @@ -320,9 +319,7 @@ class CoroutineASTTransformer : public StmtVisitor<CoroutineASTTransformer>

void VisitCoawaitExpr(CoawaitExpr* stmt)
{
if(not mFinalSuspend) {
++mSuspendsCount;
}
++mSuspendsCount;

if(const bool returnsVoid{stmt->getResumeExpr()->getType()->isVoidType()}; returnsVoid) {
Visit(stmt->getOperand());
Expand Down Expand Up @@ -391,13 +388,9 @@ class CoroutineASTTransformer : public StmtVisitor<CoroutineASTTransformer>
Visit(stmt->getReturnValueInit());
Visit(stmt->getExceptionHandler());
Visit(stmt->getReturnStmtOnAllocFailure());

Visit(stmt->getFallthroughHandler());
Visit(stmt->getInitSuspendStmt());

// final suspend point doesn't need a label
mFinalSuspend = true;
Visit(stmt->getFinalSuspendStmt());
mFinalSuspend = false;
}

void VisitStmt(Stmt* stmt)
Expand Down Expand Up @@ -756,7 +749,10 @@ void CoroutinesCodeGenerator::InsertArg(const CoroutineBodyStmt* stmt)
funcBodyStmts.Add(c);
}

// InsertArg(stmt->getFallthroughHandler());
if(const auto* coReturnVoid = dyn_cast_or_null<CoreturnStmt>(stmt->getFallthroughHandler())) {
coReturnVoid->dump();
funcBodyStmts.Add(coReturnVoid);
}

auto* gotoFinalSuspend = Goto(FINAL_SUSPEND_NAME);
funcBodyStmts.Add(gotoFinalSuspend);
Expand Down Expand Up @@ -939,16 +935,14 @@ void CoroutinesCodeGenerator::InsertArg(const CoroutineSuspendExpr* stmt)
Expr* initializeInitialAwaitResume = nullptr;

auto addInitialAwaitSuspendCalled = [&] {
if(eState::FinalSuspend != mState) {
bodyStmts.Add(bop);

if(eState::InitialSuspend == mState) {
mState = eState::Body;
// https://timsong-cpp.github.io/cppwp/n4861/dcl.fct.def.coroutine#5.3
initializeInitialAwaitResume =
Assign(mASTData.mFrameAccessDeclRef, mASTData.mInitialAwaitResumeCalledField, Bool(true));
bodyStmts.Add(initializeInitialAwaitResume);
}
bodyStmts.Add(bop);

if(eState::InitialSuspend == mState) {
mState = eState::Body;
// https://timsong-cpp.github.io/cppwp/n4861/dcl.fct.def.coroutine#5.3
initializeInitialAwaitResume =
Assign(mASTData.mFrameAccessDeclRef, mASTData.mInitialAwaitResumeCalledField, Bool(true));
bodyStmts.Add(initializeInitialAwaitResume);
}
};

Expand All @@ -974,16 +968,16 @@ void CoroutinesCodeGenerator::InsertArg(const CoroutineSuspendExpr* stmt)
mOutputFormatHelper.AppendNewLine();
}

auto* suspendLabel = Label(BuildResumeLabelName(mSuspendsCount));
InsertArg(suspendLabel);

if(eState::FinalSuspend == mState) {
auto* memExpr = AccessMember(mASTData.mFrameAccessDeclRef, mASTData.mDestroyFnField, true);
auto* callCoroFSM = Call(memExpr, {mASTData.mFrameAccessDeclRef});
InsertArg(callCoroFSM);
return;
}

auto* suspendLabel = Label(BuildResumeLabelName(mSuspendsCount));
InsertArg(suspendLabel);

const auto* resumeExpr = stmt->getResumeExpr();

if(not resumeExpr->getType()->isVoidType()) {
Expand Down
3 changes: 3 additions & 0 deletions tests/EduCoroutineAllocFailureTest.expect
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@ void __fun_intResume(__fun_intFrame * __f)
switch(__f->__suspend_index) {
case 0: break;
case 1: goto __resume_fun_int_1;
case 2: goto __resume_fun_int_2;
}

/* co_await EduCoroutineAllocFailureTest.cpp:40 */
Expand Down Expand Up @@ -234,9 +235,11 @@ void __fun_intResume(__fun_intFrame * __f)
__f->__suspend_40_14_1 = __f->__promise.final_suspend();
if(!__f->__suspend_40_14_1.await_ready()) {
__f->__suspend_40_14_1.await_suspend(std::coroutine_handle<generator<int>::promise_type>::from_address(static_cast<void *>(__f)).operator std::coroutine_handle<void>());
__f->__suspend_index = 2;
return;
}

__resume_fun_int_2:
__f->destroy_fn(__f);
}

Expand Down
3 changes: 3 additions & 0 deletions tests/EduCoroutineBinaryExprTest.expect
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ void __seqResume(__seqFrame * __f)
case 3: goto __resume_seq_3;
case 4: goto __resume_seq_4;
case 5: goto __resume_seq_5;
case 6: goto __resume_seq_6;
}

/* co_await EduCoroutineBinaryExprTest.cpp:35 */
Expand Down Expand Up @@ -216,9 +217,11 @@ void __seqResume(__seqFrame * __f)
__f->__suspend_35_11_1 = __f->__promise.final_suspend();
if(!__f->__suspend_35_11_1.await_ready()) {
__f->__suspend_35_11_1.await_suspend(std::coroutine_handle<generator::promise_type>::from_address(static_cast<void *>(__f)).operator std::coroutine_handle<void>());
__f->__suspend_index = 6;
return;
}

__resume_seq_6:
__f->destroy_fn(__f);
}

Expand Down
4 changes: 2 additions & 2 deletions tests/EduCoroutineCaptureConstTest.cerr
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
.tmp.cpp:82:15: note: non-static data member 'start' declared const here
82 | const int & start;
| ~~~~~~~~~~~~^~~~~
.tmp.cpp:147:12: error: no viable overloaded '='
147 | __f->s = {0, '\0'};
.tmp.cpp:148:12: error: no viable overloaded '='
148 | __f->s = {0, '\0'};
| ~~~~~~ ^ ~~~~~~~~~
.tmp.cpp:84:10: note: candidate function (the implicit copy assignment operator) not viable: 'this' argument has type 'const S', but method is not marked const
84 | struct S
Expand Down
3 changes: 3 additions & 0 deletions tests/EduCoroutineCaptureConstTest.expect
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ void __seqResume(__seqFrame * __f)
switch(__f->__suspend_index) {
case 0: break;
case 1: goto __resume_seq_1;
case 2: goto __resume_seq_2;
}

/* co_await EduCoroutineCaptureConstTest.cpp:35 */
Expand Down Expand Up @@ -162,9 +163,11 @@ void __seqResume(__seqFrame * __f)
__f->__suspend_35_11_1 = __f->__promise.final_suspend();
if(!__f->__suspend_35_11_1.await_ready()) {
__f->__suspend_35_11_1.await_suspend(std::coroutine_handle<generator::promise_type>::from_address(static_cast<void *>(__f)).operator std::coroutine_handle<void>());
__f->__suspend_index = 2;
return;
}

__resume_seq_2:
__f->destroy_fn(__f);
}

Expand Down
3 changes: 3 additions & 0 deletions tests/EduCoroutineCaptureThisTest.expect
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ inline my_resumable coro(int x)
switch(__f->__suspend_index) {
case 0: break;
case 1: goto __resume_coro_1;
case 2: goto __resume_coro_2;
}

/* co_await EduCoroutineCaptureThisTest.cpp:31 */
Expand Down Expand Up @@ -150,9 +151,11 @@ inline my_resumable coro(int x)
__f->__suspend_31_16_1 = __f->__promise.final_suspend();
if(!__f->__suspend_31_16_1.await_ready()) {
__f->__suspend_31_16_1.await_suspend(std::coroutine_handle<my_resumable::promise_type>::from_address(static_cast<void *>(__f)).operator std::coroutine_handle<void>());
__f->__suspend_index = 2;
return;
}

__resume_coro_2:
__f->destroy_fn(__f);
}

Expand Down
4 changes: 2 additions & 2 deletions tests/EduCoroutineCoAwaitOperatorTest.cerr
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
.tmp.cpp:167:3: error: unknown type name 'awaiter'
167 | awaiter __suspend_54_5;
| ^
.tmp.cpp:249:10: warning: expression result unused [-Wunused-value]
249 | __f->__suspend_56_14_res;
.tmp.cpp:250:10: warning: expression result unused [-Wunused-value]
250 | __f->__suspend_56_14_res;
| ~~~ ^~~~~~~~~~~~~~~~~~~
1 warning and 1 error generated.
5 changes: 5 additions & 0 deletions tests/EduCoroutineCoAwaitOperatorTest.expect
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,7 @@ void __gResume(__gFrame * __f)
case 1: goto __resume_g_1;
case 2: goto __resume_g_2;
case 3: goto __resume_g_3;
case 4: goto __resume_g_4;
}

/* co_await EduCoroutineCoAwaitOperatorTest.cpp:51 */
Expand Down Expand Up @@ -247,6 +248,8 @@ void __gResume(__gFrame * __f)
__resume_g_3:
__f->__suspend_56_14_res = __f->__suspend_56_14.await_resume();
__f->__suspend_56_14_res;
/* co_return EduCoroutineCoAwaitOperatorTest.cpp:51 */
__f->__promise.return_void();
goto __final_suspend;
} catch(...) {
if(!__f->__initial_await_suspend_called) {
Expand All @@ -262,9 +265,11 @@ void __gResume(__gFrame * __f)
__f->__suspend_51_16_1 = __f->__promise.final_suspend();
if(!__f->__suspend_51_16_1.await_ready()) {
__f->__suspend_51_16_1.await_suspend(std::coroutine_handle<my_future<int>::promise_type>::from_address(static_cast<void *>(__f)).operator std::coroutine_handle<void>());
__f->__suspend_index = 4;
return;
}

__resume_g_4:
__f->destroy_fn(__f);
}

Expand Down
28 changes: 14 additions & 14 deletions tests/EduCoroutineCoreturnWithCoawaitTest.cerr
Original file line number Diff line number Diff line change
@@ -1,41 +1,41 @@
.tmp.cpp:274:26: error: object of type 'generator' cannot be assigned because its copy assignment operator is implicitly deleted
274 | __f->__suspend_56_24 = simpleReturn(__f->v);
.tmp.cpp:278:26: error: object of type 'generator' cannot be assigned because its copy assignment operator is implicitly deleted
278 | __f->__suspend_56_24 = simpleReturn(__f->v);
| ^
.tmp.cpp:69:10: note: copy assignment operator is implicitly deleted because 'generator' has a user-declared move constructor
69 | inline generator(generator && rhs)
| ^
.tmp.cpp:285:26: error: object of type 'generator' cannot be assigned because its copy assignment operator is implicitly deleted
285 | __f->__suspend_56_51 = simpleReturn(__f->v + 1);
.tmp.cpp:289:26: error: object of type 'generator' cannot be assigned because its copy assignment operator is implicitly deleted
289 | __f->__suspend_56_51 = simpleReturn(__f->v + 1);
| ^
.tmp.cpp:69:10: note: copy assignment operator is implicitly deleted because 'generator' has a user-declared move constructor
69 | inline generator(generator && rhs)
| ^
.tmp.cpp:407:26: error: object of type 'generator' cannot be assigned because its copy assignment operator is implicitly deleted
407 | __f->__suspend_60_24 = simpleReturn(__f->v);
.tmp.cpp:414:26: error: object of type 'generator' cannot be assigned because its copy assignment operator is implicitly deleted
414 | __f->__suspend_60_24 = simpleReturn(__f->v);
| ^
.tmp.cpp:69:10: note: copy assignment operator is implicitly deleted because 'generator' has a user-declared move constructor
69 | inline generator(generator && rhs)
| ^
.tmp.cpp:418:26: error: object of type 'generator' cannot be assigned because its copy assignment operator is implicitly deleted
418 | __f->__suspend_60_51 = simpleReturn(__f->v + 1);
.tmp.cpp:425:26: error: object of type 'generator' cannot be assigned because its copy assignment operator is implicitly deleted
425 | __f->__suspend_60_51 = simpleReturn(__f->v + 1);
| ^
.tmp.cpp:69:10: note: copy assignment operator is implicitly deleted because 'generator' has a user-declared move constructor
69 | inline generator(generator && rhs)
| ^
.tmp.cpp:429:26: error: object of type 'generator' cannot be assigned because its copy assignment operator is implicitly deleted
429 | __f->__suspend_60_80 = simpleReturn(__f->v + 2);
.tmp.cpp:436:26: error: object of type 'generator' cannot be assigned because its copy assignment operator is implicitly deleted
436 | __f->__suspend_60_80 = simpleReturn(__f->v + 2);
| ^
.tmp.cpp:69:10: note: copy assignment operator is implicitly deleted because 'generator' has a user-declared move constructor
69 | inline generator(generator && rhs)
| ^
.tmp.cpp:548:26: error: object of type 'generator' cannot be assigned because its copy assignment operator is implicitly deleted
548 | __f->__suspend_67_24 = simpleReturn(__f->v);
.tmp.cpp:558:26: error: object of type 'generator' cannot be assigned because its copy assignment operator is implicitly deleted
558 | __f->__suspend_67_24 = simpleReturn(__f->v);
| ^
.tmp.cpp:69:10: note: copy assignment operator is implicitly deleted because 'generator' has a user-declared move constructor
69 | inline generator(generator && rhs)
| ^
.tmp.cpp:559:26: error: object of type 'generator' cannot be assigned because its copy assignment operator is implicitly deleted
559 | __f->__suspend_67_51 = simpleReturn(__f->v + 1);
.tmp.cpp:569:26: error: object of type 'generator' cannot be assigned because its copy assignment operator is implicitly deleted
569 | __f->__suspend_67_51 = simpleReturn(__f->v + 1);
| ^
.tmp.cpp:69:10: note: copy assignment operator is implicitly deleted because 'generator' has a user-declared move constructor
69 | inline generator(generator && rhs)
Expand Down
12 changes: 12 additions & 0 deletions tests/EduCoroutineCoreturnWithCoawaitTest.expect
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ void __simpleReturnResume(__simpleReturnFrame * __f)
switch(__f->__suspend_index) {
case 0: break;
case 1: goto __resume_simpleReturn_1;
case 2: goto __resume_simpleReturn_2;
}

/* co_await EduCoroutineCoreturnWithCoawaitTest.cpp:50 */
Expand Down Expand Up @@ -178,9 +179,11 @@ void __simpleReturnResume(__simpleReturnFrame * __f)
__f->__suspend_50_11_1 = __f->__promise.final_suspend();
if(!__f->__suspend_50_11_1.await_ready()) {
__f->__suspend_50_11_1.await_suspend(std::coroutine_handle<generator::promise_type>::from_address(static_cast<void *>(__f)).operator std::coroutine_handle<void>());
__f->__suspend_index = 2;
return;
}

__resume_simpleReturn_2:
__f->destroy_fn(__f);
}

Expand Down Expand Up @@ -256,6 +259,7 @@ void __additionAwaitReturnResume(__additionAwaitReturnFrame * __f)
case 1: goto __resume_additionAwaitReturn_1;
case 2: goto __resume_additionAwaitReturn_2;
case 3: goto __resume_additionAwaitReturn_3;
case 4: goto __resume_additionAwaitReturn_4;
}

/* co_await EduCoroutineCoreturnWithCoawaitTest.cpp:55 */
Expand Down Expand Up @@ -308,9 +312,11 @@ void __additionAwaitReturnResume(__additionAwaitReturnFrame * __f)
__f->__suspend_55_11_1 = __f->__promise.final_suspend();
if(!__f->__suspend_55_11_1.await_ready()) {
__f->__suspend_55_11_1.await_suspend(std::coroutine_handle<generator::promise_type>::from_address(static_cast<void *>(__f)).operator std::coroutine_handle<void>());
__f->__suspend_index = 4;
return;
}

__resume_additionAwaitReturn_4:
__f->destroy_fn(__f);
}

Expand Down Expand Up @@ -389,6 +395,7 @@ void __additionAwaitReturn2Resume(__additionAwaitReturn2Frame * __f)
case 2: goto __resume_additionAwaitReturn2_2;
case 3: goto __resume_additionAwaitReturn2_3;
case 4: goto __resume_additionAwaitReturn2_4;
case 5: goto __resume_additionAwaitReturn2_5;
}

/* co_await EduCoroutineCoreturnWithCoawaitTest.cpp:59 */
Expand Down Expand Up @@ -452,9 +459,11 @@ void __additionAwaitReturn2Resume(__additionAwaitReturn2Frame * __f)
__f->__suspend_59_11_1 = __f->__promise.final_suspend();
if(!__f->__suspend_59_11_1.await_ready()) {
__f->__suspend_59_11_1.await_suspend(std::coroutine_handle<generator::promise_type>::from_address(static_cast<void *>(__f)).operator std::coroutine_handle<void>());
__f->__suspend_index = 5;
return;
}

__resume_additionAwaitReturn2_5:
__f->destroy_fn(__f);
}

Expand Down Expand Up @@ -530,6 +539,7 @@ void __additionAwaitReturnWithIntResume(__additionAwaitReturnWithIntFrame * __f)
case 1: goto __resume_additionAwaitReturnWithInt_1;
case 2: goto __resume_additionAwaitReturnWithInt_2;
case 3: goto __resume_additionAwaitReturnWithInt_3;
case 4: goto __resume_additionAwaitReturnWithInt_4;
}

/* co_await EduCoroutineCoreturnWithCoawaitTest.cpp:63 */
Expand Down Expand Up @@ -582,9 +592,11 @@ void __additionAwaitReturnWithIntResume(__additionAwaitReturnWithIntFrame * __f)
__f->__suspend_63_11_1 = __f->__promise.final_suspend();
if(!__f->__suspend_63_11_1.await_ready()) {
__f->__suspend_63_11_1.await_suspend(std::coroutine_handle<generator::promise_type>::from_address(static_cast<void *>(__f)).operator std::coroutine_handle<void>());
__f->__suspend_index = 4;
return;
}

__resume_additionAwaitReturnWithInt_4:
__f->destroy_fn(__f);
}

Expand Down
5 changes: 5 additions & 0 deletions tests/EduCoroutineCustomYieldTypeTest.expect
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,7 @@ void __seqResume(__seqFrame * __f)
case 0: break;
case 1: goto __resume_seq_1;
case 2: goto __resume_seq_2;
case 3: goto __resume_seq_3;
}

/* co_await EduCoroutineCustomYieldTypeTest.cpp:86 */
Expand Down Expand Up @@ -237,6 +238,8 @@ void __seqResume(__seqFrame * __f)
__f->__suspend_88_14.await_resume();
}

/* co_return EduCoroutineCustomYieldTypeTest.cpp:86 */
__f->__promise.return_void();
goto __final_suspend;
} catch(...) {
if(!__f->__initial_await_suspend_called) {
Expand All @@ -252,9 +255,11 @@ void __seqResume(__seqFrame * __f)
__f->__suspend_86_11_1 = __f->__promise.final_suspend();
if(!__f->__suspend_86_11_1.await_ready()) {
__f->__suspend_86_11_1.await_suspend(std::coroutine_handle<generator::promise_type>::from_address(static_cast<void *>(__f)).operator std::coroutine_handle<void>());
__f->__suspend_index = 3;
return;
}

__resume_seq_3:
__f->destroy_fn(__f);
}

Expand Down
Loading