summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Berry <stereotype441@gmail.com>2014-01-31 09:55:35 -0800
committerCarl Worth <cworth@cworth.org>2014-03-04 13:04:15 -0800
commit1b6aec4b5ab9441f979f6eae4d56787e7483cc39 (patch)
tree05a1fede709e6459107da599d944339d925e9e4b
parent6d6bdd88e708820653312edda85f536c590a669c (diff)
downloadmesa-1b6aec4b5ab9441f979f6eae4d56787e7483cc39.tar.gz
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> (cherry picked from commit 7f5740899fe8ee2d7fecebf1b9622e06dbc78f43)
-rw-r--r--src/glsl/ast_to_hir.cpp23
1 files changed, 14 insertions, 9 deletions
diff --git a/src/glsl/ast_to_hir.cpp b/src/glsl/ast_to_hir.cpp
index f7b5ac822ec..ca80f4276e6 100644
--- a/src/glsl/ast_to_hir.cpp
+++ b/src/glsl/ast_to_hir.cpp
@@ -3979,17 +3979,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) {