diff options
author | Alan Hourihane <[email protected]> | 2009-03-19 10:16:28 +0000 |
---|---|---|
committer | Alan Hourihane <[email protected]> | 2009-03-19 10:17:30 +0000 |
commit | 989856bde47d699d7e18798df4013fbf962e1d4b (patch) | |
tree | b8853a52321f61b2ae428d8dc60ebcddb8dc5e4d /src/mesa/shader/slang/slang_codegen.c | |
parent | 1342664434918af06baf07a2c190c0241fbd5a24 (diff) |
slang: if/else/break & if/else/continue work for unrolled loops
Diffstat (limited to 'src/mesa/shader/slang/slang_codegen.c')
-rw-r--r-- | src/mesa/shader/slang/slang_codegen.c | 44 |
1 files changed, 37 insertions, 7 deletions
diff --git a/src/mesa/shader/slang/slang_codegen.c b/src/mesa/shader/slang/slang_codegen.c index e98d9d96e3a..6c8c8c18563 100644 --- a/src/mesa/shader/slang/slang_codegen.c +++ b/src/mesa/shader/slang/slang_codegen.c @@ -2575,6 +2575,20 @@ _slang_can_unroll_for_loop(slang_assemble_ctx * A, const slang_operation *oper) } +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. @@ -2591,6 +2605,9 @@ _slang_unroll_for_loop(slang_assemble_ctx * A, const slang_operation *oper) 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; @@ -2613,11 +2630,15 @@ _slang_unroll_for_loop(slang_assemble_ctx * A, const slang_operation *oper) /* 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' */ { @@ -2628,6 +2649,7 @@ _slang_unroll_for_loop(slang_assemble_ctx * A, const slang_operation *oper) if (!oldVar) { /* undeclared loop variable */ slang_operation_delete(body); + _unroll_loop_dec( A ); return NULL; } @@ -2642,14 +2664,18 @@ _slang_unroll_for_loop(slang_assemble_ctx * A, const slang_operation *oper) /* 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; } @@ -2786,7 +2812,7 @@ _slang_gen_if(slang_assemble_ctx * A, const slang_operation *oper) 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; @@ -2794,7 +2820,7 @@ _slang_gen_if(slang_assemble_ctx * A, const slang_operation *oper) 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; @@ -2802,6 +2828,8 @@ _slang_gen_if(slang_assemble_ctx * A, const slang_operation *oper) 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 @@ -4014,13 +4042,15 @@ _slang_gen_operation(slang_assemble_ctx * A, slang_operation *oper) 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); |