On 1 August 2011 17:29, Dan McCabe <zen3d.li...@gmail.com> wrote: > This patch set adds support for switch statements to the GLSL compiler. We > modify the grammar for the compiler with productions for switch statements > and case labels, while adding supporting supporting productions not already > present. New AST classes are defined to support those productions. However, > with our approach no new IR is needed, allowing us to leverage all existing > optimizations and code generation. > > Regarding the grammar, we note that the grammar as summarized in the appendix > of the GLSL specs leaves a bit to be desired. For example, it appears that > case > labels can be used anywhere a statement is valid. However, we note that the > description of the switch statement in Section 6.2 in the body of the spec is > much more specific, and we follow that text to guide our creation of new > productions. > > Specifically, we add productions for: > switch body, > case label list, > case statement, and > case statement list. > The switch body and the case statement allow us to limit where case labels may > be used. > > In turn, we create new AST classes for each of these productions. > > For code generation, we generate previously existing IR. Switch statements > can be thought of a series of if/then/else statements. Case labels are > compared with the value of a test expression and the case statements are > executed if the comparison is true. > > There are a couple of aspects of switch statements that complicate this > simplistic view. The primary one is that cases can fall through sequentially > to subsequent cases, unless a break statement is encountered, in which case > the switch statement exits completely. > > But break handling is further complicated by the fact that a break statement > can impact the exit of a loop. Thus, we need to coordinate break processing > between switch statements and loop statements. > > The code generated by a switch statement maintains three temporary state > variables: > int test_value; > bool is_fallthru; > bool is_break; > > test_value is initialized to the value of the test expression at the head of > the switch statement. This is the value that case labels are compared against. > > is_fallthru is used to sequentially fall through to subsequent cases and is > initialized to false. When a case label matches the test expression, this > state variable is set to true. It will also be forced to false if a break > statement has been encountered. This forcing to false on break MUST be > after every case test. In practice, we defer that forcing to immediately after > the last case comparison prior to executing a case statement, but that is > an optimization. > > is_break is used to indicate that a break statement has been executed and is > initialized to false. When a break statement is encountered, it is set to > true. > This state variable is then used to conditionally force is_fallthru to to > false > to prevent subsequent case statements from executing. > > Code generation for break statements depends on whether the break statement is > inside a switch statement or inside a loop statement. If it inside a loop > statement is inside a break statement, the same code as before gets generated. > But if a switch statement is inside a loop statement, code is emitted to set > the is_break state to true. > > Just as ASTs for loop statements are managed in a stack-like manner to handle > nesting, we also add a bool to capture the innermost switch or loop condition. > Note that we still need to maintain a loop AST stack to properly handle > for-loop code generation on a continue statement. Technically, we don't (yet) > need a switch AST stack, but we are using one for orthogonality with loop > statements and in anticipation of potential future use. Note that a simple > boolean stack would have sufficed. > > We will illustrate a switch statement with its analogous conditional code that > a switch statement corresponds to by considering an example. > > Consider the following switch statement: > switch (42) { > case 0: > case 1: > gl_FragColor = vec4(1.0, 2.0, 3.0, 4.0); > case 2: > case 3: > gl_FragColor = vec4(4.0, 3.0, 2.0, 1.0); > break; > case 4: > default: > gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0); > } > > Note that case 0 and case 1 fall through to cases 2 and 3 if they occur. > > Note that case 4 and the default case must be reached explicitly, since cases > 2 and 3 break at the end of their case. > > Finally, note that case 4 and the default case don't break but simply fall > through to the end of the switch. > > For this code, the equivalent code can be expressed as: > int test_val = 42; // capture value of test expression > bool is_fallthru = false; // prevent initial fall throughs > bool is_break = false; // capture the execution of a break stmt > > is_fallthru |= (test_val == 0); // enable fallthru on case 0 > is_fallthru |= (test_val == 1); // enable fallthru on case 1 > is_fallthru &= !is_break; // inhibit fallthru on previous break > if (is_fallthru) { > gl_FragColor = vec4(1.0, 2.0, 3.0, 4.0); > } > > is_fallthru |= (test_val == 2); // enable fallthru on case 2 > is_fallthru |= (test_val == 3); // enable fallthru on case 3 > is_fallthru &= !is_break; // inhibit fallthru on previous break > if (is_fallthru) { > gl_FragColor = vec4(4.0, 3.0, 2.0, 1.0); > is_break = true; // inhibit all subsequent fallthru for break > } > > is_fallthru |= (test_val == 4); // enable fallthru on case 4 > is_fallthru = true; // enable fallthru for default case > is_fallthru &= !is_break; // inhibit fallthru on previous break > if (is_fallthru) { > gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0); > } > > The code generate for |= and &= uses the conditional assignment capabilities > of the IR. > > _______________________________________________ > mesa-dev mailing list > mesa-dev@lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/mesa-dev >
Do we have tests for any of this code (e.g. in Piglit)? It would be nice to check that this code passes tests that we know pass on other platforms. _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev