}
+static void
+_unroll_loop_inc(slang_assemble_ctx * A)
+{
+ A->UnrollLoop++;
+}
+
+
+static void
+_unroll_loop_dec(slang_assemble_ctx * A)
+{
+ A->UnrollLoop--;
+}
+
+
/**
* Unroll a for-loop.
* First we determine the number of iterations to unroll.
slang_ir_node *n, *root = NULL;
slang_atom varId;
+ /* Set flag so code generator knows we're unrolling loops */
+ _unroll_loop_inc( A );
+
if (oper->children[0].type == SLANG_OPER_BLOCK_NO_NEW_SCOPE) {
/* for (int i=0; ... */
slang_variable *var;
/* make a copy of the loop body */
body = slang_operation_new(1);
- if (!body)
+ if (!body) {
+ _unroll_loop_dec( A );
return NULL;
+ }
- if (!slang_operation_copy(body, &oper->children[3]))
+ if (!slang_operation_copy(body, &oper->children[3])) {
+ _unroll_loop_dec( A );
return NULL;
+ }
/* in body, replace instances of 'varId' with literal 'iter' */
{
if (!oldVar) {
/* undeclared loop variable */
slang_operation_delete(body);
+ _unroll_loop_dec( A );
return NULL;
}
/* do IR codegen for body */
n = _slang_gen_operation(A, body);
- if (!n)
+ if (!n) {
+ _unroll_loop_dec( A );
return NULL;
+ }
root = new_seq(root, n);
slang_operation_delete(body);
}
+ _unroll_loop_dec( A );
+
return root;
}
if (is_operation_type(&oper->children[1], SLANG_OPER_BREAK)
&& !haveElseClause) {
/* Special case: generate a conditional break */
- if (!A->CurLoop) /* probably trying to unroll */
+ if (!A->CurLoop && A->UnrollLoop) /* trying to unroll */
return NULL;
ifBody = new_break_if_true(A->CurLoop, cond);
return ifBody;
else if (is_operation_type(&oper->children[1], SLANG_OPER_CONTINUE)
&& !haveElseClause) {
/* Special case: generate a conditional continue */
- if (!A->CurLoop) /* probably trying to unroll */
+ if (!A->CurLoop && A->UnrollLoop) /* trying to unroll */
return NULL;
ifBody = new_cont_if_true(A->CurLoop, cond);
return ifBody;
else {
/* general case */
ifBody = _slang_gen_operation(A, &oper->children[1]);
+ if (!ifBody)
+ return NULL;
if (haveElseClause)
elseBody = _slang_gen_operation(A, &oper->children[2]);
else
return _slang_gen_while(A, oper);
case SLANG_OPER_BREAK:
if (!A->CurLoop) {
- slang_info_log_error(A->log, "'break' not in loop");
+ if (!A->UnrollLoop)
+ slang_info_log_error(A->log, "'break' not in loop");
return NULL;
}
return new_break(A->CurLoop);
case SLANG_OPER_CONTINUE:
if (!A->CurLoop) {
- slang_info_log_error(A->log, "'continue' not in loop");
+ if (!A->UnrollLoop)
+ slang_info_log_error(A->log, "'continue' not in loop");
return NULL;
}
return _slang_gen_continue(A, oper);