* @brief Splits the given "while True" loop @a stmt into three parts. * * @param[in] stmt "while True" loop to be splitted. * @param[in] indVarInfo * * See the description of SplittedWhileTrueLoop for more details. * * Each statement in the loop will be cloned by calling @c clone() on it. * * If the loop either isn't a "while True" loop or it cannot be splitted into * the three parts, the null poi
| 112 | * the three parts, the null pointer is returned. |
| 113 | */ |
| 114 | ShPtr<SplittedWhileTrueLoop> splitWhileTrueLoop( |
| 115 | ShPtr<WhileLoopStmt> stmt, |
| 116 | ShPtr<IndVarInfo> indVarInfo) { |
| 117 | // It has to be a "while True" loop. |
| 118 | if (!isWhileTrueLoop(stmt)) { |
| 119 | return {}; |
| 120 | } |
| 121 | |
| 122 | // Split the loop. |
| 123 | auto splittedLoop = std::make_shared<SplittedWhileTrueLoop>(); |
| 124 | ShPtr<Expression> exitCond; |
| 125 | auto currStmt = stmt->getBody(); |
| 126 | while (currStmt) { |
| 127 | // When a statement in the loop is a goto target, we cannot split the |
| 128 | // loop. Otherwise, after optimizing the loop, we might end up with |
| 129 | // incorrect code. |
| 130 | if (currStmt->isGotoTarget()) { |
| 131 | return {}; |
| 132 | } |
| 133 | |
| 134 | // If there is more than one loop end, use the first one. |
| 135 | if (isLoopEnd(currStmt) && !exitCond) { |
| 136 | exitCond = getExitCondition(currStmt); |
| 137 | splittedLoop->loopEnd = cast<IfStmt>(currStmt); |
| 138 | currStmt = currStmt->getSuccessor(); |
| 139 | continue; |
| 140 | } |
| 141 | |
| 142 | if (exitCond) { |
| 143 | // TODO This can be done more efficiently. |
| 144 | splittedLoop->afterLoopEndStmts = Statement::mergeStatements( |
| 145 | splittedLoop->afterLoopEndStmts, ucast<Statement>(currStmt->clone())); |
| 146 | } else { |
| 147 | // TODO This can be done more efficiently. |
| 148 | if (indVarInfo == nullptr |
| 149 | || !indVarInfo->updateBeforeExit |
| 150 | || currStmt != indVarInfo->updateStmt) { |
| 151 | splittedLoop->beforeLoopEndStmts = Statement::mergeStatements( |
| 152 | splittedLoop->beforeLoopEndStmts, ucast<Statement>(currStmt->clone())); |
| 153 | } |
| 154 | } |
| 155 | |
| 156 | currStmt = currStmt->getSuccessor(); |
| 157 | } |
| 158 | |
| 159 | // Check that the loop has been successfully splitted. |
| 160 | if (!splittedLoop->loopEnd || !exitCond) { |
| 161 | return {}; |
| 162 | } |
| 163 | |
| 164 | return splittedLoop; |
| 165 | } |
| 166 | |
| 167 | /** |
| 168 | * @brief Returns information about the induction variable in the given "while |
no test coverage detected