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.latv...@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 +# +# 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]] + +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, 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@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev