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

Dan McCabe zen3d.linux at gmail.com
Wed Aug 3 13:33:12 PDT 2011


On 08/03/2011 12:39 PM, Paul Berry wrote:
> 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.
Negatory. I have some private tests that I used to validate the code and 
that will be migrated into Piglit by EOD Friday, but they aren't in 
Piglit yet.

cheers, danm


More information about the mesa-dev mailing list