[Mesa-dev] [PATCH 3/9] glsl: Refactor the python test case generator

Petri Latvala petri.latvala at intel.com
Mon Aug 18 06:33:02 PDT 2014


On 08/13/2014 01:51 AM, Dylan Baker wrote:
> On Tuesday, July 29, 2014 12:36:33 PM Petri Latvala wrote:
>> Move the IR sexp builder helpers and test script creation parts of
>> tests/lower_jumps/create_test_cases.py into tests/test_case_generator.py
>>
>> No functional changes.
>>
>> Signed-off-by: Petri Latvala <petri.latvala at intel.com>
>> ---
>>   src/glsl/tests/lower_jumps/create_test_cases.py | 336 +++---------------------
>>   src/glsl/tests/test_case_generator.py           | 293 +++++++++++++++++++++
>>   2 files changed, 334 insertions(+), 295 deletions(-)
>>   create mode 100644 src/glsl/tests/test_case_generator.py
>>
>> diff --git a/src/glsl/tests/lower_jumps/create_test_cases.py b/src/glsl/tests/lower_jumps/create_test_cases.py
>> index 3be1079..9783627 100644
>> --- a/src/glsl/tests/lower_jumps/create_test_cases.py
>> +++ b/src/glsl/tests/lower_jumps/create_test_cases.py
>> @@ -27,278 +27,9 @@ import re
>>   import subprocess
>>   import sys
>>   
>> -sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..')) # For access to sexps.py, which is in parent dir
>> +sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..')) # For access to sexps.py and test_case_generator.py, which are in parent dir
>>   from sexps import *
>> -
>> -def make_test_case(f_name, ret_type, body):
>> -    """Create a simple optimization test case consisting of a single
>> -    function with the given name, return type, and body.
>> -
>> -    Global declarations are automatically created for any undeclared
>> -    variables that are referenced by the function.  All undeclared
>> -    variables are assumed to be floats.
>> -    """
>> -    check_sexp(body)
>> -    declarations = {}
>> -    def make_declarations(sexp, already_declared = ()):
>> -        if isinstance(sexp, list):
>> -            if len(sexp) == 2 and sexp[0] == 'var_ref':
>> -                if sexp[1] not in already_declared:
>> -                    declarations[sexp[1]] = [
>> -                        'declare', ['in'], 'float', sexp[1]]
>> -            elif len(sexp) == 4 and sexp[0] == 'assign':
>> -                assert sexp[2][0] == 'var_ref'
>> -                if sexp[2][1] not in already_declared:
>> -                    declarations[sexp[2][1]] = [
>> -                        'declare', ['out'], 'float', sexp[2][1]]
>> -                make_declarations(sexp[3], already_declared)
>> -            else:
>> -                already_declared = set(already_declared)
>> -                for s in sexp:
>> -                    if isinstance(s, list) and len(s) >= 4 and \
>> -                            s[0] == 'declare':
>> -                        already_declared.add(s[3])
>> -                    else:
>> -                        make_declarations(s, already_declared)
>> -    make_declarations(body)
>> -    return declarations.values() + \
>> -        [['function', f_name, ['signature', ret_type, ['parameters'], body]]]
>> -
>> -
>> -# The following functions can be used to build expressions.
>> -
>> -def const_float(value):
>> -    """Create an expression representing the given floating point value."""
>> -    return ['constant', 'float', ['{0:.6f}'.format(value)]]
>> -
>> -def const_bool(value):
>> -    """Create an expression representing the given boolean value.
>> -
>> -    If value is not a boolean, it is converted to a boolean.  So, for
>> -    instance, const_bool(1) is equivalent to const_bool(True).
>> -    """
>> -    return ['constant', 'bool', ['{0}'.format(1 if value else 0)]]
>> -
>> -def gt_zero(var_name):
>> -    """Create Construct the expression var_name > 0"""
>> -    return ['expression', 'bool', '>', ['var_ref', var_name], const_float(0)]
>> -
>> -
>> -# The following functions can be used to build complex control flow
>> -# statements.  All of these functions return statement lists (even
>> -# those which only create a single statement), so that statements can
>> -# be sequenced together using the '+' operator.
>> -
>> -def return_(value = None):
>> -    """Create a return statement."""
>> -    if value is not None:
>> -        return [['return', value]]
>> -    else:
>> -        return [['return']]
>> -
>> -def break_():
>> -    """Create a break statement."""
>> -    return ['break']
>> -
>> -def continue_():
>> -    """Create a continue statement."""
>> -    return ['continue']
>> -
>> -def simple_if(var_name, then_statements, else_statements = None):
>> -    """Create a statement of the form
>> -
>> -    if (var_name > 0.0) {
>> -       <then_statements>
>> -    } else {
>> -       <else_statements>
>> -    }
>> -
>> -    else_statements may be omitted.
>> -    """
>> -    if else_statements is None:
>> -        else_statements = []
>> -    check_sexp(then_statements)
>> -    check_sexp(else_statements)
>> -    return [['if', gt_zero(var_name), then_statements, else_statements]]
>> -
>> -def loop(statements):
>> -    """Create a loop containing the given statements as its loop
>> -    body.
>> -    """
>> -    check_sexp(statements)
>> -    return [['loop', statements]]
>> -
>> -def declare_temp(var_type, var_name):
>> -    """Create a declaration of the form
>> -
>> -    (declare (temporary) <var_type> <var_name)
>> -    """
>> -    return [['declare', ['temporary'], var_type, var_name]]
>> -
>> -def assign_x(var_name, value):
>> -    """Create a statement that assigns <value> to the variable
>> -    <var_name>.  The assignment uses the mask (x).
>> -    """
>> -    check_sexp(value)
>> -    return [['assign', ['x'], ['var_ref', var_name], value]]
>> -
>> -def complex_if(var_prefix, statements):
>> -    """Create a statement of the form
>> -
>> -    if (<var_prefix>a > 0.0) {
>> -       if (<var_prefix>b > 0.0) {
>> -          <statements>
>> -       }
>> -    }
>> -
>> -    This is useful in testing jump lowering, because if <statements>
>> -    ends in a jump, lower_jumps.cpp won't try to combine this
>> -    construct with the code that follows it, as it might do for a
>> -    simple if.
>> -
>> -    All variables used in the if statement are prefixed with
>> -    var_prefix.  This can be used to ensure uniqueness.
>> -    """
>> -    check_sexp(statements)
>> -    return simple_if(var_prefix + 'a', simple_if(var_prefix + 'b', statements))
>> -
>> -def declare_execute_flag():
>> -    """Create the statements that lower_jumps.cpp uses to declare and
>> -    initialize the temporary boolean execute_flag.
>> -    """
>> -    return declare_temp('bool', 'execute_flag') + \
>> -        assign_x('execute_flag', const_bool(True))
>> -
>> -def declare_return_flag():
>> -    """Create the statements that lower_jumps.cpp uses to declare and
>> -    initialize the temporary boolean return_flag.
>> -    """
>> -    return declare_temp('bool', 'return_flag') + \
>> -        assign_x('return_flag', const_bool(False))
>> -
>> -def declare_return_value():
>> -    """Create the statements that lower_jumps.cpp uses to declare and
>> -    initialize the temporary variable return_value.  Assume that
>> -    return_value is a float.
>> -    """
>> -    return declare_temp('float', 'return_value')
>> -
>> -def declare_break_flag():
>> -    """Create the statements that lower_jumps.cpp uses to declare and
>> -    initialize the temporary boolean break_flag.
>> -    """
>> -    return declare_temp('bool', 'break_flag') + \
>> -        assign_x('break_flag', const_bool(False))
>> -
>> -def lowered_return_simple(value = None):
>> -    """Create the statements that lower_jumps.cpp lowers a return
>> -    statement to, in situations where it does not need to clear the
>> -    execute flag.
>> -    """
>> -    if value:
>> -        result = assign_x('return_value', value)
>> -    else:
>> -        result = []
>> -    return result + assign_x('return_flag', const_bool(True))
>> -
>> -def lowered_return(value = None):
>> -    """Create the statements that lower_jumps.cpp lowers a return
>> -    statement to, in situations where it needs to clear the execute
>> -    flag.
>> -    """
>> -    return lowered_return_simple(value) + \
>> -        assign_x('execute_flag', const_bool(False))
>> -
>> -def lowered_continue():
>> -    """Create the statement that lower_jumps.cpp lowers a continue
>> -    statement to.
>> -    """
>> -    return assign_x('execute_flag', const_bool(False))
>> -
>> -def lowered_break_simple():
>> -    """Create the statement that lower_jumps.cpp lowers a break
>> -    statement to, in situations where it does not need to clear the
>> -    execute flag.
>> -    """
>> -    return assign_x('break_flag', const_bool(True))
>> -
>> -def lowered_break():
>> -    """Create the statement that lower_jumps.cpp lowers a break
>> -    statement to, in situations where it needs to clear the execute
>> -    flag.
>> -    """
>> -    return lowered_break_simple() + assign_x('execute_flag', const_bool(False))
>> -
>> -def if_execute_flag(statements):
>> -    """Wrap statements in an if test so that they will only execute if
>> -    execute_flag is True.
>> -    """
>> -    check_sexp(statements)
>> -    return [['if', ['var_ref', 'execute_flag'], statements, []]]
>> -
>> -def if_not_return_flag(statements):
>> -    """Wrap statements in an if test so that they will only execute if
>> -    return_flag is False.
>> -    """
>> -    check_sexp(statements)
>> -    return [['if', ['var_ref', 'return_flag'], [], statements]]
>> -
>> -def final_return():
>> -    """Create the return statement that lower_jumps.cpp places at the
>> -    end of a function when lowering returns.
>> -    """
>> -    return [['return', ['var_ref', 'return_value']]]
>> -
>> -def final_break():
>> -    """Create the conditional break statement that lower_jumps.cpp
>> -    places at the end of a function when lowering breaks.
>> -    """
>> -    return [['if', ['var_ref', 'break_flag'], break_(), []]]
>> -
>> -def bash_quote(*args):
>> -    """Quote the arguments appropriately so that bash will understand
>> -    each argument as a single word.
>> -    """
>> -    def quote_word(word):
>> -        for c in word:
>> -            if not (c.isalpha() or c.isdigit() or c in '@%_-+=:,./'):
>> -                break
>> -        else:
>> -            if not word:
>> -                return "''"
>> -            return word
>> -        return "'{0}'".format(word.replace("'", "'\"'\"'"))
>> -    return ' '.join(quote_word(word) for word in args)
>> -
>> -def create_test_case(doc_string, input_sexp, expected_sexp, test_name,
>> -                     pull_out_jumps=False, lower_sub_return=False,
>> -                     lower_main_return=False, lower_continue=False,
>> -                     lower_break=False):
>> -    """Create a test case that verifies that do_lower_jumps transforms
>> -    the given code in the expected way.
>> -    """
>> -    doc_lines = [line.strip() for line in doc_string.splitlines()]
>> -    doc_string = ''.join('# {0}\n'.format(line) for line in doc_lines if line != '')
>> -    check_sexp(input_sexp)
>> -    check_sexp(expected_sexp)
>> -    input_str = sexp_to_string(sort_decls(input_sexp))
>> -    expected_output = sexp_to_string(sort_decls(expected_sexp))
>> -
>> -    optimization = (
>> -        'do_lower_jumps({0:d}, {1:d}, {2:d}, {3:d}, {4:d})'.format(
>> -            pull_out_jumps, lower_sub_return, lower_main_return,
>> -            lower_continue, lower_break))
>> -    args = ['../../glsl_test', 'optpass', '--quiet', '--input-ir', optimization]
>> -    test_file = '{0}.opt_test'.format(test_name)
>> -    with open(test_file, 'w') as f:
>> -        f.write('#!/usr/bin/env bash\n#\n# This file was generated by create_test_cases.py.\n#\n')
>> -        f.write(doc_string)
>> -        f.write('{0} <<EOF\n'.format(bash_quote(*args)))
>> -        f.write('{0}\nEOF\n'.format(input_str))
>> -    os.chmod(test_file, 0774)
>> -    expected_file = '{0}.opt_test.expected'.format(test_name)
>> -    with open(expected_file, 'w') as f:
>> -        f.write('{0}\n'.format(expected_output))
>> +from test_case_generator import *
>>   
>>   def test_lower_returns_main():
>>       doc_string = """Test that do_lower_jumps respects the lower_main_return
>> @@ -314,9 +45,9 @@ def test_lower_returns_main():
>>               complex_if('', lowered_return())
>>               ))
>>       create_test_case(doc_string, input_sexp, expected_sexp, 'lower_returns_main_true',
>> -                     lower_main_return=True)
>> +                     create_opt_string(lower_main_return=True))
>>       create_test_case(doc_string, input_sexp, input_sexp, 'lower_returns_main_false',
>> -                     lower_main_return=False)
>> +                     create_opt_string(lower_main_return=False))
>>   
>>   def test_lower_returns_sub():
>>       doc_string = """Test that do_lower_jumps respects the lower_sub_return flag
>> @@ -331,9 +62,9 @@ def test_lower_returns_sub():
>>               complex_if('', lowered_return())
>>               ))
>>       create_test_case(doc_string, input_sexp, expected_sexp, 'lower_returns_sub_true',
>> -                     lower_sub_return=True)
>> +                     create_opt_string(lower_sub_return=True))
>>       create_test_case(doc_string, input_sexp, input_sexp, 'lower_returns_sub_false',
>> -                     lower_sub_return=False)
>> +                     create_opt_string(lower_sub_return=False))
>>   
>>   def test_lower_returns_1():
>>       doc_string = """Test that a void return at the end of a function is
>> @@ -347,7 +78,7 @@ def test_lower_returns_1():
>>               assign_x('a', const_float(1))
>>               ))
>>       create_test_case(doc_string, input_sexp, expected_sexp, 'lower_returns_1',
>> -                     lower_main_return=True)
>> +                     create_opt_string(lower_main_return=True))
>>   
>>   def test_lower_returns_2():
>>       doc_string = """Test that lowering is not performed on a non-void return at
>> @@ -358,7 +89,7 @@ def test_lower_returns_2():
>>               return_(const_float(1))
>>               ))
>>       create_test_case(doc_string, input_sexp, input_sexp, 'lower_returns_2',
>> -                     lower_sub_return=True)
>> +                     create_opt_string(lower_sub_return=True))
>>   
>>   def test_lower_returns_3():
>>       doc_string = """Test lowering of returns when there is one nested inside a
>> @@ -381,7 +112,7 @@ def test_lower_returns_3():
>>               final_return()
>>               ))
>>       create_test_case(doc_string, input_sexp, expected_sexp, 'lower_returns_3',
>> -                     lower_sub_return=True)
>> +                     create_opt_string(lower_sub_return=True))
>>   
>>   def test_lower_returns_4():
>>       doc_string = """Test that returns are properly lowered when they occur in
>> @@ -400,7 +131,7 @@ def test_lower_returns_4():
>>               final_return()
>>               ))
>>       create_test_case(doc_string, input_sexp, expected_sexp, 'lower_returns_4',
>> -                     lower_sub_return=True)
>> +                     create_opt_string(lower_sub_return=True))
>>   
>>   def test_lower_unified_returns():
>>       doc_string = """If both branches of an if statement end in a return, and
>> @@ -423,7 +154,7 @@ def test_lower_unified_returns():
>>                                               lowered_return())))
>>               ))
>>       create_test_case(doc_string, input_sexp, expected_sexp, 'lower_unified_returns',
>> -                     lower_main_return=True, pull_out_jumps=True)
>> +                     create_opt_string(lower_main_return=True, pull_out_jumps=True))
>>   
>>   def test_lower_pulled_out_jump():
>>       doc_string = """If one branch of an if ends in a jump, and control cannot
>> @@ -455,7 +186,7 @@ def test_lower_pulled_out_jump():
>>                   if_not_return_flag(assign_x('d', const_float(1))))
>>               ))
>>       create_test_case(doc_string, input_sexp, expected_sexp, 'lower_pulled_out_jump',
>> -                     lower_main_return=True, pull_out_jumps=True)
>> +                     create_opt_string(lower_main_return=True, pull_out_jumps=True))
>>   
>>   def test_lower_breaks_1():
>>       doc_string = """If a loop contains an unconditional break at the bottom of
>> @@ -465,7 +196,8 @@ def test_lower_breaks_1():
>>                    break_())
>>               ))
>>       expected_sexp = input_sexp
>> -    create_test_case(doc_string, input_sexp, expected_sexp, 'lower_breaks_1', lower_break=True)
>> +    create_test_case(doc_string, input_sexp, expected_sexp, 'lower_breaks_1',
>> +                     create_opt_string(lower_break=True))
>>   
>>   def test_lower_breaks_2():
>>       doc_string = """If a loop contains a conditional break at the bottom of it,
>> @@ -476,7 +208,8 @@ def test_lower_breaks_2():
>>                    simple_if('b', break_()))
>>               ))
>>       expected_sexp = input_sexp
>> -    create_test_case(doc_string, input_sexp, expected_sexp, 'lower_breaks_2', lower_break=True)
>> +    create_test_case(doc_string, input_sexp, expected_sexp, 'lower_breaks_2',
>> +                     create_opt_string(lower_break=True))
>>   
>>   def test_lower_breaks_3():
>>       doc_string = """If a loop contains a conditional break at the bottom of it,
>> @@ -489,7 +222,8 @@ def test_lower_breaks_3():
>>                                    break_())))
>>               ))
>>       expected_sexp = input_sexp
>> -    create_test_case(doc_string, input_sexp, expected_sexp, 'lower_breaks_3', lower_break=True)
>> +    create_test_case(doc_string, input_sexp, expected_sexp, 'lower_breaks_3',
>> +                     create_opt_string(lower_break=True))
>>   
>>   def test_lower_breaks_4():
>>       doc_string = """If a loop contains a conditional break at the bottom of it,
>> @@ -500,7 +234,8 @@ def test_lower_breaks_4():
>>                    simple_if('b', [], break_()))
>>               ))
>>       expected_sexp = input_sexp
>> -    create_test_case(doc_string, input_sexp, expected_sexp, 'lower_breaks_4', lower_break=True)
>> +    create_test_case(doc_string, input_sexp, expected_sexp, 'lower_breaks_4',
>> +                     create_opt_string(lower_break=True))
>>   
>>   def test_lower_breaks_5():
>>       doc_string = """If a loop contains a conditional break at the bottom of it,
>> @@ -513,7 +248,8 @@ def test_lower_breaks_5():
>>                                        break_())))
>>               ))
>>       expected_sexp = input_sexp
>> -    create_test_case(doc_string, input_sexp, expected_sexp, 'lower_breaks_5', lower_break=True)
>> +    create_test_case(doc_string, input_sexp, expected_sexp, 'lower_breaks_5',
>> +                     create_opt_string(lower_break=True))
>>   
>>   def test_lower_breaks_6():
>>       doc_string = """If a loop contains conditional breaks and continues, and
>> @@ -538,7 +274,7 @@ def test_lower_breaks_6():
>>                    final_break())
>>               ))
>>       create_test_case(doc_string, input_sexp, expected_sexp, 'lower_breaks_6',
>> -                     lower_break=True, lower_continue=True)
>> +                     create_opt_string(lower_break=True, lower_continue=True))
>>   
>>   def test_lower_guarded_conditional_break():
>>       doc_string = """Normally a conditional break at the end of a loop isn't
>> @@ -558,7 +294,7 @@ def test_lower_guarded_conditional_break():
>>                    final_break())
>>               ))
>>       create_test_case(doc_string, input_sexp, expected_sexp, 'lower_guarded_conditional_break',
>> -                     lower_break=True, lower_continue=True)
>> +                     create_opt_string(lower_break=True, lower_continue=True))
>>   
>>   def test_remove_continue_at_end_of_loop():
>>       doc_string = """Test that a redundant continue-statement at the end of a
>> @@ -571,7 +307,8 @@ def test_remove_continue_at_end_of_loop():
>>       expected_sexp = make_test_case('main', 'void', (
>>               loop(assign_x('a', const_float(1)))
>>               ))
>> -    create_test_case(doc_string, input_sexp, expected_sexp, 'remove_continue_at_end_of_loop')
>> +    create_test_case(doc_string, input_sexp, expected_sexp, 'remove_continue_at_end_of_loop',
>> +                     create_opt_string())
>>   
>>   def test_lower_return_void_at_end_of_loop():
>>       doc_string = """Test that a return of void at the end of a loop is properly
>> @@ -589,11 +326,12 @@ def test_lower_return_void_at_end_of_loop():
>>                    break_()) +
>>               if_not_return_flag(assign_x('b', const_float(2)))
>>               ))
>> -    create_test_case(doc_string, input_sexp, input_sexp, 'return_void_at_end_of_loop_lower_nothing')
>> +    create_test_case(doc_string, input_sexp, input_sexp, 'return_void_at_end_of_loop_lower_nothing',
>> +                     create_opt_string())
>>       create_test_case(doc_string, input_sexp, expected_sexp, 'return_void_at_end_of_loop_lower_return',
>> -                     lower_main_return=True)
>> +                     create_opt_string(lower_main_return=True))
>>       create_test_case(doc_string, input_sexp, expected_sexp, 'return_void_at_end_of_loop_lower_return_and_break',
>> -                     lower_main_return=True, lower_break=True)
>> +                     create_opt_string(lower_main_return=True, lower_break=True))
>>   
>>   def test_lower_return_non_void_at_end_of_loop():
>>       doc_string = """Test that a non-void return at the end of a loop is
>> @@ -616,11 +354,19 @@ def test_lower_return_non_void_at_end_of_loop():
>>                                  lowered_return(const_float(4))) +
>>               final_return()
>>               ))
>> -    create_test_case(doc_string, input_sexp, input_sexp, 'return_non_void_at_end_of_loop_lower_nothing')
>> +    create_test_case(doc_string, input_sexp, input_sexp, 'return_non_void_at_end_of_loop_lower_nothing',
>> +                     create_opt_string())
>>       create_test_case(doc_string, input_sexp, expected_sexp, 'return_non_void_at_end_of_loop_lower_return',
>> -                     lower_sub_return=True)
>> +                     create_opt_string(lower_sub_return=True))
>>       create_test_case(doc_string, input_sexp, expected_sexp, 'return_non_void_at_end_of_loop_lower_return_and_break',
>> -                     lower_sub_return=True, lower_break=True)
>> +                     create_opt_string(lower_sub_return=True, lower_break=True))
>> +
>> +def create_opt_string(pull_out_jumps=False, lower_sub_return=False,
>> +                      lower_main_return=False, lower_continue=False,
>> +                      lower_break=False):
>> +    return ('do_lower_jumps({0:d}, {1:d}, {2:d}, {3:d}, {4:d})'.format(
>> +            pull_out_jumps, lower_sub_return, lower_main_return,
>> +            lower_continue, lower_break))
>>   
>>   if __name__ == '__main__':
>>       test_lower_returns_main()
>> diff --git a/src/glsl/tests/test_case_generator.py b/src/glsl/tests/test_case_generator.py
>> new file mode 100644
>> index 0000000..d6754fc8
>> --- /dev/null
>> +++ b/src/glsl/tests/test_case_generator.py
>> @@ -0,0 +1,293 @@
>> +# coding=utf-8
>> +#
>> +# Copyright © 2011 Intel Corporation
> 2014?

Yes, later patches should change this to 2011-2014.

>> +#
>> +# Permission is hereby granted, free of charge, to any person obtaining a
>> +# copy of this software and associated documentation files (the "Software"),
>> +# to deal in the Software without restriction, including without limitation
>> +# the rights to use, copy, modify, merge, publish, distribute, sublicense,
>> +# and/or sell copies of the Software, and to permit persons to whom the
>> +# Software is furnished to do so, subject to the following conditions:
>> +#
>> +# The above copyright notice and this permission notice (including the next
>> +# paragraph) shall be included in all copies or substantial portions of the
>> +# Software.
>> +#
>> +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
>> +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
>> +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
>> +# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
>> +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
>> +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
>> +# DEALINGS IN THE SOFTWARE.
>> +
>> +import os
>> +import os.path
>> +import re
>> +import subprocess
>> +import sys
>> +
>> +from sexps import *
>> +
>> +def make_test_case(f_name, ret_type, body):
>> +    """Create a simple optimization test case consisting of a single
>> +    function with the given name, return type, and body.
>> +
>> +    Global declarations are automatically created for any undeclared
>> +    variables that are referenced by the function.  All undeclared
>> +    variables are assumed to be floats.
>> +    """
>> +    check_sexp(body)
>> +    declarations = {}
>> +    def make_declarations(sexp, already_declared = ()):
>> +        if isinstance(sexp, list):
>> +            if len(sexp) == 2 and sexp[0] == 'var_ref':
>> +                if sexp[1] not in already_declared:
>> +                    declarations[sexp[1]] = [
>> +                        'declare', ['in'], 'float', sexp[1]]
>> +            elif len(sexp) == 4 and sexp[0] == 'assign':
>> +                assert sexp[2][0] == 'var_ref'
>> +                if sexp[2][1] not in already_declared:
>> +                    declarations[sexp[2][1]] = [
>> +                        'declare', ['out'], 'float', sexp[2][1]]
>> +                make_declarations(sexp[3], already_declared)
>> +            else:
>> +                already_declared = set(already_declared)
>> +                for s in sexp:
>> +                    if isinstance(s, list) and len(s) >= 4 and \
>> +                            s[0] == 'declare':
>> +                        already_declared.add(s[3])
>> +                    else:
>> +                        make_declarations(s, already_declared)
>> +    make_declarations(body)
>> +    return declarations.values() + \
>> +        [['function', f_name, ['signature', ret_type, ['parameters'], body]]]
>> +
>> +
>> +# The following functions can be used to build expressions.
>> +
>> +def const_float(value):
>> +    """Create an expression representing the given floating point value."""
>> +    return ['constant', 'float', ['{0:.6f}'.format(value)]]
>> +
>> +def const_bool(value):
>> +    """Create an expression representing the given boolean value.
>> +
>> +    If value is not a boolean, it is converted to a boolean.  So, for
>> +    instance, const_bool(1) is equivalent to const_bool(True).
>> +    """
>> +    return ['constant', 'bool', ['{0}'.format(1 if value else 0)]]
>> +
>> +def gt_zero(var_name):
>> +    """Create Construct the expression var_name > 0"""
>> +    return ['expression', 'bool', '>', ['var_ref', var_name], const_float(0)]
>> +
>> +
>> +# The following functions can be used to build complex control flow
>> +# statements.  All of these functions return statement lists (even
>> +# those which only create a single statement), so that statements can
>> +# be sequenced together using the '+' operator.
>> +
>> +def return_(value = None):
>> +    """Create a return statement."""
>> +    if value is not None:
>> +        return [['return', value]]
>> +    else:
>> +        return [['return']]
>> +
>> +def break_():
>> +    """Create a break statement."""
>> +    return ['break']
>> +
>> +def continue_():
>> +    """Create a continue statement."""
>> +    return ['continue']
>> +
>> +def simple_if(var_name, then_statements, else_statements = None):
>> +    """Create a statement of the form
>> +
>> +    if (var_name > 0.0) {
>> +       <then_statements>
>> +    } else {
>> +       <else_statements>
>> +    }
>> +
>> +    else_statements may be omitted.
>> +    """
>> +    if else_statements is None:
>> +        else_statements = []
>> +    check_sexp(then_statements)
>> +    check_sexp(else_statements)
>> +    return [['if', gt_zero(var_name), then_statements, else_statements]]
>> +
>> +def loop(statements):
>> +    """Create a loop containing the given statements as its loop
>> +    body.
>> +    """
>> +    check_sexp(statements)
>> +    return [['loop', statements]]
> This whole file is incredibly hard to read, could you make some
> formating changes?
>
> Block docstrings should be formatted like follows:
> """My docstring
>
> This is a description of the function or class
>
> """
> do_something()
>
> Note the extra blank space, this improves readability a lot

This particular patch is just a cut&paste-refactor of the code to a 
different file, with minimal changes for ease of review. I can add an 
additional cleanup patch according to your comments. (This comment and 
the ones below)

>> +
>> +def declare_temp(var_type, var_name):
>> +    """Create a declaration of the form
>> +
>> +    (declare (temporary) <var_type> <var_name)
>> +    """
>> +    return [['declare', ['temporary'], var_type, var_name]]
>> +
>> +def assign_x(var_name, value):
>> +    """Create a statement that assigns <value> to the variable
>> +    <var_name>.  The assignment uses the mask (x).
>> +    """
>> +    check_sexp(value)
>> +    return [['assign', ['x'], ['var_ref', var_name], value]]
>> +
>> +def complex_if(var_prefix, statements):
>> +    """Create a statement of the form
>> +
>> +    if (<var_prefix>a > 0.0) {
>> +       if (<var_prefix>b > 0.0) {
>> +          <statements>
>> +       }
>> +    }
>> +
>> +    This is useful in testing jump lowering, because if <statements>
>> +    ends in a jump, lower_jumps.cpp won't try to combine this
>> +    construct with the code that follows it, as it might do for a
>> +    simple if.
>> +
>> +    All variables used in the if statement are prefixed with
>> +    var_prefix.  This can be used to ensure uniqueness.
>> +    """
>> +    check_sexp(statements)
>> +    return simple_if(var_prefix + 'a', simple_if(var_prefix + 'b', statements))
>> +
>> +def declare_execute_flag():
>> +    """Create the statements that lower_jumps.cpp uses to declare and
>> +    initialize the temporary boolean execute_flag.
>> +    """
>> +    return declare_temp('bool', 'execute_flag') + \
>> +        assign_x('execute_flag', const_bool(True))
>> +
>> +def declare_return_flag():
>> +    """Create the statements that lower_jumps.cpp uses to declare and
>> +    initialize the temporary boolean return_flag.
>> +    """
>> +    return declare_temp('bool', 'return_flag') + \
>> +        assign_x('return_flag', const_bool(False))
>> +
>> +def declare_return_value():
>> +    """Create the statements that lower_jumps.cpp uses to declare and
>> +    initialize the temporary variable return_value.  Assume that
>> +    return_value is a float.
>> +    """
>> +    return declare_temp('float', 'return_value')
>> +
>> +def declare_break_flag():
>> +    """Create the statements that lower_jumps.cpp uses to declare and
>> +    initialize the temporary boolean break_flag.
>> +    """
>> +    return declare_temp('bool', 'break_flag') + \
>> +        assign_x('break_flag', const_bool(False))
>> +
>> +def lowered_return_simple(value = None):
>> +    """Create the statements that lower_jumps.cpp lowers a return
>> +    statement to, in situations where it does not need to clear the
>> +    execute flag.
>> +    """
>> +    if value:
>> +        result = assign_x('return_value', value)
>> +    else:
>> +        result = []
>> +    return result + assign_x('return_flag', const_bool(True))
>> +
>> +def lowered_return(value = None):
>> +    """Create the statements that lower_jumps.cpp lowers a return
>> +    statement to, in situations where it needs to clear the execute
>> +    flag.
>> +    """
>> +    return lowered_return_simple(value) + \
>> +        assign_x('execute_flag', const_bool(False))
>> +
>> +def lowered_continue():
>> +    """Create the statement that lower_jumps.cpp lowers a continue
>> +    statement to.
>> +    """
>> +    return assign_x('execute_flag', const_bool(False))
>> +
>> +def lowered_break_simple():
>> +    """Create the statement that lower_jumps.cpp lowers a break
>> +    statement to, in situations where it does not need to clear the
>> +    execute flag.
>> +    """
>> +    return assign_x('break_flag', const_bool(True))
>> +
>> +def lowered_break():
>> +    """Create the statement that lower_jumps.cpp lowers a break
>> +    statement to, in situations where it needs to clear the execute
>> +    flag.
>> +    """
>> +    return lowered_break_simple() + assign_x('execute_flag', const_bool(False))
>> +
>> +def if_execute_flag(statements):
>> +    """Wrap statements in an if test so that they will only execute if
>> +    execute_flag is True.
>> +    """
>> +    check_sexp(statements)
>> +    return [['if', ['var_ref', 'execute_flag'], statements, []]]
>> +
>> +def if_not_return_flag(statements):
>> +    """Wrap statements in an if test so that they will only execute if
>> +    return_flag is False.
>> +    """
>> +    check_sexp(statements)
>> +    return [['if', ['var_ref', 'return_flag'], [], statements]]
>> +
>> +def final_return():
>> +    """Create the return statement that lower_jumps.cpp places at the
>> +    end of a function when lowering returns.
>> +    """
>> +    return [['return', ['var_ref', 'return_value']]]
>> +
>> +def final_break():
>> +    """Create the conditional break statement that lower_jumps.cpp
>> +    places at the end of a function when lowering breaks.
>> +    """
>> +    return [['if', ['var_ref', 'break_flag'], break_(), []]]
>> +
>> +def bash_quote(*args):
>> +    """Quote the arguments appropriately so that bash will understand
>> +    each argument as a single word.
>> +    """
>> +    def quote_word(word):
> What exactly are you looking to do here? You might have a look at
> shlex.split(), I think it will do what you want. something like:
> shlex.split(''.join(args)).
>
>> +        for c in word:
>> +            if not (c.isalpha() or c.isdigit() or c in '@%_-+=:,./'):
>> +                break
>> +        else:
>> +            if not word:
>> +                return "''"
>> +            return word
>> +        return "'{0}'".format(word.replace("'", "'\"'\"'"))
> feel free to ad a blank line here, it makes this much easier to read
>
>> +    return ' '.join(quote_word(word) for word in args)
>> +
>> +def create_test_case(doc_string, input_sexp, expected_sexp, test_name, optimization):
>> +    """Create a test case that verifies that the given optimization pass transforms
>> +    the given code in the expected way.
>> +    """
>> +    doc_lines = [line.strip() for line in doc_string.splitlines()]
>> +    doc_string = ''.join('# {0}\n'.format(line) for line in doc_lines if line != '')
>> +    check_sexp(input_sexp)
>> +    check_sexp(expected_sexp)
>> +    input_str = sexp_to_string(sort_decls(input_sexp))
>> +    expected_output = sexp_to_string(sort_decls(expected_sexp))
>> +
>> +    args = ['../../glsl_test', 'optpass', '--quiet', '--input-ir', optimization]
>> +    test_file = '{0}.opt_test'.format(test_name)
>> +    with open(test_file, 'w') as f:
>> +        f.write('#!/usr/bin/env bash\n#\n# This file was automatically generated.\n#\n')
>> +        f.write(doc_string)
>> +        f.write('{0} <<EOF\n'.format(bash_quote(*args)))
>> +        f.write('{0}\nEOF\n'.format(input_str))
>> +    os.chmod(test_file, 0774)
>> +    expected_file = '{0}.opt_test.expected'.format(test_name)
>> +    with open(expected_file, 'w') as f:
>> +        f.write('{0}\n'.format(expected_output))
>> -- 
>> 2.0.1
>>
>> _______________________________________________
>> mesa-dev mailing list
>> mesa-dev at lists.freedesktop.org
>> http://lists.freedesktop.org/mailman/listinfo/mesa-dev
>>



More information about the mesa-dev mailing list