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

Reply via email to