| 710 | //----------------------------------------------------------------------------- |
| 711 | |
| 712 | void CoroutinesCodeGenerator::InsertArg(const CoroutineBodyStmt* stmt) |
| 713 | { |
| 714 | // insert a made up switch for continuing a resume |
| 715 | SwitchStmt* sstmt = Switch(mASTData.mSuspendIndexAccess); |
| 716 | |
| 717 | // insert 0 with break for consistency |
| 718 | auto* initialSuspendCase = Case(0, Break()); |
| 719 | StmtsContainer switchBodyStmts{initialSuspendCase}; |
| 720 | |
| 721 | for(const auto& i : NumberIterator{mSuspendsCounter}) { |
| 722 | switchBodyStmts.Add(Case(i + 1, Goto(BuildResumeLabelName(i + 1)))); |
| 723 | } |
| 724 | |
| 725 | auto* switchBody = mkCompoundStmt(switchBodyStmts); |
| 726 | sstmt->setBody(switchBody); |
| 727 | |
| 728 | StmtsContainer funcBodyStmts{ |
| 729 | Comment("Create a switch to get to the correct resume point"sv), sstmt, stmt->getInitSuspendStmt()}; |
| 730 | |
| 731 | // insert the init suspend expr |
| 732 | mState = eState::InitialSuspend; |
| 733 | |
| 734 | if(mASTData.mThisExprs.size()) { |
| 735 | AddField(kwInternalThis, mASTData.mThisExprs.at(0)->getType()); |
| 736 | } |
| 737 | |
| 738 | mInsertVarDecl = false; |
| 739 | mSupressRecordDecls = true; |
| 740 | |
| 741 | for(const auto* c : stmt->getBody()->children()) { |
| 742 | funcBodyStmts.Add(c); |
| 743 | } |
| 744 | |
| 745 | if(const auto* coReturnVoid = dyn_cast_or_null<CoreturnStmt>(stmt->getFallthroughHandler())) { |
| 746 | funcBodyStmts.Add(coReturnVoid); |
| 747 | } |
| 748 | |
| 749 | auto* gotoFinalSuspend = Goto(FINAL_SUSPEND_NAME); |
| 750 | funcBodyStmts.Add(gotoFinalSuspend); |
| 751 | |
| 752 | auto* body = [&]() -> Stmt* { |
| 753 | auto* tryBody = mkCompoundStmt(funcBodyStmts); |
| 754 | |
| 755 | // First open the try-catch block, as we get an error when jumping across such blocks with goto |
| 756 | if(const auto* exceptionHandler = stmt->getExceptionHandler()) { |
| 757 | // If we encounter an exceptionbefore inital_suspend's await_suspend was called we re-throw the |
| 758 | // exception. |
| 759 | auto* ifStmt = If(Not(mASTData.mInitialAwaitResumeCalledAccess), Throw()); |
| 760 | |
| 761 | StmtsContainer catchBodyStmts{ifStmt, exceptionHandler}; |
| 762 | |
| 763 | return Try(tryBody, Catch(catchBodyStmts)); |
| 764 | } |
| 765 | |
| 766 | return tryBody; |
| 767 | }(); |
| 768 | |
| 769 | InsertArg(body); |
no test coverage detected