63 std::unique_ptr<Expression>* loopTest,
70 auto loopInfo = std::make_unique<LoopUnrollInfo>();
75 if (!loopInitializer) {
77 errors.error(
pos,
"missing init declaration");
81 errors.error(loopInitializer->
fPosition,
"invalid init declaration");
86 errors.error(loopInitializer->
fPosition,
"invalid type for loop index");
90 errors.error(loopInitializer->
fPosition,
"invalid type for loop index");
93 if (!initDecl.
value()) {
94 errors.error(loopInitializer->
fPosition,
"missing loop index initializer");
99 "loop index initializer must be a constant expression");
103 loopInfo->fIndex = initDecl.
var();
105 auto is_loop_index = [&](
const std::unique_ptr<Expression>& expr) {
113 if (!loopTest || !*loopTest) {
115 errors.error(
pos,
"missing condition");
119 errors.error(loopTest->get()->fPosition,
"invalid condition");
123 if (!is_loop_index(cond->
left())) {
124 errors.error(cond->
fPosition,
"expected loop index on left hand side of condition");
129 case Operator::Kind::GT:
130 case Operator::Kind::GTEQ:
131 case Operator::Kind::LT:
132 case Operator::Kind::LTEQ:
133 case Operator::Kind::EQEQ:
134 case Operator::Kind::NEQ:
137 errors.error(cond->
fPosition,
"invalid relational operator");
142 errors.error(cond->
fPosition,
"loop index must be compared with a constant expression");
157 errors.error(
pos,
"missing loop expression");
160 switch (loopNext->
kind()) {
161 case Expression::Kind::kBinary: {
163 if (!is_loop_index(
next.left())) {
164 errors.error(loopNext->
fPosition,
"expected loop index in loop expression");
169 "loop index must be modified by a constant expression");
172 switch (
next.getOperator().kind()) {
173 case Operator::Kind::PLUSEQ:
break;
174 case Operator::Kind::MINUSEQ: loopInfo->fDelta = -loopInfo->fDelta;
break;
176 errors.error(loopNext->
fPosition,
"invalid operator in loop expression");
181 case Expression::Kind::kPrefix: {
183 if (!is_loop_index(
next.operand())) {
184 errors.error(loopNext->
fPosition,
"expected loop index in loop expression");
187 switch (
next.getOperator().kind()) {
188 case Operator::Kind::PLUSPLUS: loopInfo->fDelta = 1;
break;
189 case Operator::Kind::MINUSMINUS: loopInfo->fDelta = -1;
break;
191 errors.error(loopNext->
fPosition,
"invalid operator in loop expression");
196 case Expression::Kind::kPostfix: {
198 if (!is_loop_index(
next.operand())) {
199 errors.error(loopNext->
fPosition,
"expected loop index in loop expression");
202 switch (
next.getOperator().kind()) {
203 case Operator::Kind::PLUSPLUS: loopInfo->fDelta = 1;
break;
204 case Operator::Kind::MINUSMINUS: loopInfo->fDelta = -1;
break;
206 errors.error(loopNext->
fPosition,
"invalid operator in loop expression");
212 errors.error(loopNext->
fPosition,
"invalid loop expression");
222 "loop index must not be modified within body of the loop");
227 loopInfo->fCount = 0;
230 case Operator::Kind::LT:
231 loopInfo->fCount =
calculate_count(loopInfo->fStart, loopEnd, loopInfo->fDelta,
235 case Operator::Kind::GT:
236 loopInfo->fCount =
calculate_count(loopInfo->fStart, loopEnd, loopInfo->fDelta,
240 case Operator::Kind::LTEQ:
241 loopInfo->fCount =
calculate_count(loopInfo->fStart, loopEnd, loopInfo->fDelta,
245 case Operator::Kind::GTEQ:
246 loopInfo->fCount =
calculate_count(loopInfo->fStart, loopEnd, loopInfo->fDelta,
250 case Operator::Kind::NEQ: {
252 loopInfo->fCount = std::ceil(iterations);
253 if (loopInfo->fCount < 0 || loopInfo->fCount != iterations ||
254 !std::isfinite(iterations)) {
258 if (loopInfo->fIndex->type().componentType().isFloat()) {
262 : Operator::Kind::GT;
265 cond->
left()->clone(),
267 cond->
right()->clone());
272 case Operator::Kind::EQEQ: {
273 if (loopInfo->fStart == loopEnd) {
275 if (loopInfo->fDelta) {
277 loopInfo->fCount = 1;
284 loopInfo->fCount = 0;
293 errors.error(loopPos,
"loop must guarantee termination in fewer iterations");
std::unique_ptr< LoopUnrollInfo > GetLoopUnrollInfo(const Context &context, Position pos, const ForLoopPositions &positions, const Statement *loopInitializer, std::unique_ptr< Expression > *loopTestPtr, const Expression *loopNext, const Statement *loopStatement, ErrorReporter *errors)