[Mesa-dev] [PATCH 0/5] glsl: Add switch statement support to the GLSL compiler.

Paul Berry stereotype441 at gmail.com
Wed Aug 3 12:39:42 PDT 2011


On 1 August 2011 17:29, Dan McCabe <zen3d.linux at 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 at 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.


More information about the mesa-dev mailing list