glsl: Fix continue statements in do-while loops.
From the GLSL 4.40 spec, section 6.4 (Jumps):
The continue jump is used only in loops. It skips the remainder of
the body of the inner most loop of which it is inside. For while
and do-while loops, this jump is to the next evaluation of the
loop condition-expression from which the loop continues as
previously defined.
Previously, we incorrectly treated a "continue" statement as jumping
to the top of a do-while loop.
This patch fixes the problem by replicating the loop condition when
converting the "continue" statement to IR. (We already do a similar
thing in "for" loops, to ensure that "continue" causes the loop
expression to be executed).
Fixes piglit tests:
- glsl-fs-continue-inside-do-while.shader_test
- glsl-vs-continue-inside-do-while.shader_test
- glsl-fs-continue-in-switch-in-do-while.shader_test
- glsl-vs-continue-in-switch-in-do-while.shader_test
Cc: mesa-stable@lists.freedesktop.org
Acked-by: Carl Worth <cworth@cworth.org>
Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
Reviewed-by: Matt Turner <mattst88@gmail.com>
This commit is contained in:
+14
-9
@@ -4029,17 +4029,22 @@ ast_jump_statement::hir(exec_list *instructions,
|
||||
_mesa_glsl_error(& loc, state,
|
||||
"break may only appear in a loop or a switch");
|
||||
} else {
|
||||
/* For a loop, inline the for loop expression again,
|
||||
* since we don't know where near the end of
|
||||
* the loop body the normal copy of it
|
||||
* is going to be placed.
|
||||
/* For a loop, inline the for loop expression again, since we don't
|
||||
* know where near the end of the loop body the normal copy of it is
|
||||
* going to be placed. Same goes for the condition for a do-while
|
||||
* loop.
|
||||
*/
|
||||
if (state->loop_nesting_ast != NULL &&
|
||||
mode == ast_continue &&
|
||||
state->loop_nesting_ast->rest_expression) {
|
||||
state->loop_nesting_ast->rest_expression->hir(instructions,
|
||||
state);
|
||||
}
|
||||
mode == ast_continue) {
|
||||
if (state->loop_nesting_ast->rest_expression) {
|
||||
state->loop_nesting_ast->rest_expression->hir(instructions,
|
||||
state);
|
||||
}
|
||||
if (state->loop_nesting_ast->mode ==
|
||||
ast_iteration_statement::ast_do_while) {
|
||||
state->loop_nesting_ast->condition_to_hir(instructions, state);
|
||||
}
|
||||
}
|
||||
|
||||
if (state->switch_state.is_switch_innermost &&
|
||||
mode == ast_break) {
|
||||
|
||||
Reference in New Issue
Block a user