glsl: drop last remaining lower jump test

This test only tests that a redundant continue is removed. This test is
not very useful and there are hundreds of lines of supporting test
infrastructure that can be removed if we drop it.

Reviewed-by: Marek Olšák <marek.olsak@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/32364>
This commit is contained in:
Timothy Arceri 2024-11-27 16:44:28 +11:00 committed by Marge Bot
parent cf188a0efb
commit 722f939614
8 changed files with 0 additions and 903 deletions

View file

@ -259,20 +259,6 @@ glsl_compiler = executable(
install : with_tools.contains('glsl'),
)
glsl_test = executable(
'glsl_test',
['test.cpp', 'test_optpass.cpp', 'test_optpass.h',
ir_expression_operation_h],
c_args : [c_msvc_compat_args, no_override_init_args],
cpp_args : [cpp_msvc_compat_args],
gnu_symbol_visibility : 'hidden',
include_directories : [inc_include, inc_src, inc_mapi, inc_mesa, inc_gallium, inc_gallium_aux],
dependencies : [dep_clock, dep_thread, idep_getopt, idep_mesautil, idep_compiler],
link_with : [libglsl, libglsl_standalone, libglsl_util],
build_by_default : with_tools.contains('glsl'),
install : with_tools.contains('glsl'),
)
if with_any_opengl and with_tests
subdir('tests')
endif

View file

@ -1,78 +0,0 @@
/*
* 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.
*/
/**
* \file test.cpp
*
* Standalone tests for the GLSL compiler.
*
* This file provides a standalone executable which can be used to
* test components of the GLSL.
*
* Each test is a function with the same signature as main(). The
* main function interprets its first argument as the name of the test
* to run, strips out that argument, and then calls the test function.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "test_optpass.h"
/**
* Print proper usage and exit with failure.
*/
static void
usage_fail(const char *name)
{
printf("*** usage: %s <command> <options>\n", name);
printf("\n");
printf("Possible commands are:\n");
printf(" optpass: test an optimization pass in isolation\n");
exit(EXIT_FAILURE);
}
static const char *extract_command_from_argv(int *argc, char **argv)
{
if (*argc < 2) {
usage_fail(argv[0]);
}
const char *command = argv[1];
--*argc;
memmove(&argv[1], &argv[2], (*argc) * sizeof(argv[1]));
return command;
}
int main(int argc, char **argv)
{
const char *command = extract_command_from_argv(&argc, argv);
if (strcmp(command, "optpass") == 0) {
return test_optpass(argc, argv);
} else {
usage_fail(argv[0]);
}
/* Execution should never reach here. */
return EXIT_FAILURE;
}

View file

@ -1,237 +0,0 @@
/*
* 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.
*/
/**
* \file test_optpass.cpp
*
* Standalone test for optimization passes.
*
* This file provides the "optpass" command for the standalone
* glsl_test app. It accepts either GLSL or high-level IR as input,
* and performs the optimiation passes specified on the command line.
* It outputs the IR, both before and after optimiations.
*/
#include <string>
#include <iostream>
#include <sstream>
#include <getopt.h>
#include "ast.h"
#include "ir_optimization.h"
#include "program.h"
#include "ir_reader.h"
#include "standalone_scaffolding.h"
#include "main/mtypes.h"
using namespace std;
static string read_stdin_to_eof()
{
stringbuf sb;
cin.get(sb, '\0');
return sb.str();
}
static GLboolean
do_optimization(struct exec_list *ir, const char *optimization,
const struct gl_shader_compiler_options *options)
{
int int_0;
int int_1;
int int_2;
int int_3;
if (sscanf(optimization, "do_common_optimization ( %d ) ", &int_0) == 1) {
return do_common_optimization(ir, int_0 != 0, options, true);
} else if (strcmp(optimization, "do_algebraic") == 0) {
return do_algebraic(ir, true, options);
} else if (strcmp(optimization, "do_dead_code") == 0) {
return do_dead_code(ir);
} else if (strcmp(optimization, "do_dead_code_local") == 0) {
return do_dead_code_local(ir);
} else if (strcmp(optimization, "do_dead_code_unlinked") == 0) {
return do_dead_code_unlinked(ir);
} else if (sscanf(optimization,
"do_lower_jumps ( %d , %d , %d , %d ) ",
&int_0, &int_1, &int_2, &int_3) == 4) {
return do_lower_jumps(ir, int_0 != 0, int_3 != 0);
} else if (strcmp(optimization, "do_if_simplification") == 0) {
return do_if_simplification(ir);
} else if (strcmp(optimization, "do_mat_op_to_vec") == 0) {
return do_mat_op_to_vec(ir);
} else if (strcmp(optimization, "do_tree_grafting") == 0) {
return do_tree_grafting(ir);
} else if (strcmp(optimization, "do_vec_index_to_cond_assign") == 0) {
return do_vec_index_to_cond_assign(ir);
} else if (sscanf(optimization, "lower_instructions ( %d ) ",
&int_0) == 1) {
return lower_instructions(ir, false, false);
} else {
printf("Unrecognized optimization %s\n", optimization);
exit(EXIT_FAILURE);
return false;
}
}
static GLboolean
do_optimization_passes(struct exec_list *ir, char **optimizations,
int num_optimizations, bool quiet,
const struct gl_shader_compiler_options *options)
{
GLboolean overall_progress = false;
for (int i = 0; i < num_optimizations; ++i) {
const char *optimization = optimizations[i];
if (!quiet) {
printf("*** Running optimization %s...", optimization);
}
GLboolean progress = do_optimization(ir, optimization, options);
if (!quiet) {
printf("%s\n", progress ? "progress" : "no progress");
}
validate_ir_tree(ir);
overall_progress = overall_progress || progress;
}
return overall_progress;
}
int test_optpass(int argc, char **argv)
{
int input_format_ir = 0; /* 0=glsl, 1=ir */
int loop = 0;
int shader_type = GL_VERTEX_SHADER;
int quiet = 0;
int error;
const struct option optpass_opts[] = {
{ "input-ir", no_argument, &input_format_ir, 1 },
{ "input-glsl", no_argument, &input_format_ir, 0 },
{ "loop", no_argument, &loop, 1 },
{ "vertex-shader", no_argument, &shader_type, GL_VERTEX_SHADER },
{ "fragment-shader", no_argument, &shader_type, GL_FRAGMENT_SHADER },
{ "quiet", no_argument, &quiet, 1 },
{ NULL, 0, NULL, 0 }
};
int idx = 0;
int c;
while ((c = getopt_long(argc, argv, "", optpass_opts, &idx)) != -1) {
if (c != 0) {
printf("*** usage: %s optpass <optimizations> <options>\n", argv[0]);
printf("\n");
printf("Possible options are:\n");
printf(" --input-ir: input format is IR\n");
printf(" --input-glsl: input format is GLSL (the default)\n");
printf(" --loop: run optimizations repeatedly until no progress\n");
printf(" --vertex-shader: test with a vertex shader (the default)\n");
printf(" --fragment-shader: test with a fragment shader\n");
exit(EXIT_FAILURE);
}
}
glsl_type_singleton_init_or_ref();
struct gl_context local_ctx;
struct gl_context *ctx = &local_ctx;
initialize_context_to_defaults(ctx, API_OPENGL_COMPAT);
ir_variable::temporaries_allocate_names = true;
struct gl_shader *shader = rzalloc(NULL, struct gl_shader);
shader->Type = shader_type;
shader->Stage = _mesa_shader_enum_to_shader_stage(shader_type);
string input = read_stdin_to_eof();
struct _mesa_glsl_parse_state *state
= new(shader) _mesa_glsl_parse_state(ctx, shader->Stage, shader);
if (input_format_ir) {
shader->ir = new(shader) exec_list;
_mesa_glsl_initialize_types(state);
_mesa_glsl_read_ir(state, shader->ir, input.c_str(), true);
} else {
shader->Source = input.c_str();
const char *source = shader->Source;
state->error = glcpp_preprocess(state, &source, &state->info_log,
NULL, NULL, ctx) != 0;
if (!state->error) {
_mesa_glsl_lexer_ctor(state, source);
_mesa_glsl_parse(state);
_mesa_glsl_lexer_dtor(state);
}
shader->ir = new(shader) exec_list;
if (!state->error && !state->translation_unit.is_empty())
_mesa_ast_to_hir(shader->ir, state);
}
/* Print out the initial IR */
if (!state->error && !quiet) {
printf("*** pre-optimization IR:\n");
_mesa_print_ir(stdout, shader->ir, state);
printf("\n--\n");
}
/* Optimization passes */
if (!state->error) {
GLboolean progress;
const struct gl_shader_compiler_options *options =
&ctx->Const.ShaderCompilerOptions[_mesa_shader_enum_to_shader_stage(shader_type)];
do {
progress = do_optimization_passes(shader->ir, &argv[optind],
argc - optind, quiet != 0, options);
} while (loop && progress);
}
/* Print out the resulting IR */
if (!state->error) {
if (!quiet) {
printf("*** resulting IR:\n");
}
_mesa_print_ir(stdout, shader->ir, state);
if (!quiet) {
printf("\n--\n");
}
}
if (state->error) {
printf("*** error(s) occurred:\n");
printf("%s\n", state->info_log);
printf("--\n");
}
error = state->error;
ralloc_free(state);
ralloc_free(shader);
glsl_type_singleton_decref();
return error;
}

View file

@ -1,29 +0,0 @@
/*
* 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.
*/
#ifndef TEST_OPTPASS_H
#define TEST_OPTPASS_H
int test_optpass(int argc, char **argv);
#endif /* TEST_OPTPASS_H */

View file

@ -1,307 +0,0 @@
# coding=utf-8
#
# Copyright © 2011, 2018 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.
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 list(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', '<', const_float(0), ['var_ref', var_name]]
# 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_return_flag(then_statements, else_statements):
"""Wrap statements in an if test with return_flag as the condition.
"""
check_sexp(then_statements)
check_sexp(else_statements)
return [['if', ['var_ref', 'return_flag'], then_statements, else_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(input_sexp, expected_sexp, test_name,
pull_out_jumps=False, lower_sub_return=False,
lower_main_return=False, lower_continue=False):
"""Create a test case that verifies that do_lower_jumps transforms
the given code in the expected way.
"""
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)) # XXX: don't stringify this
optimization = (
'do_lower_jumps({0:d}, {1:d}, {2:d}, {3:d})'.format(
pull_out_jumps, lower_sub_return, lower_main_return,
lower_continue))
return (test_name, optimization, input_str, expected_output)
def test_remove_continue_at_end_of_loop():
"""Test that a redundant continue-statement at the end of a loop is
removed.
"""
input_sexp = make_test_case('main', 'void', (
loop(assign_x('a', const_float(1)) +
continue_())
))
expected_sexp = make_test_case('main', 'void', (
loop(assign_x('a', const_float(1)))
))
yield create_test_case(input_sexp, expected_sexp, 'remove_continue_at_end_of_loop')
CASES = [
test_remove_continue_at_end_of_loop,
]

View file

@ -72,16 +72,6 @@ if meson.can_run_host_binaries()
suite : ['compiler', 'glsl'],
timeout: 60,
)
test(
'glsl optimization',
prog_python,
args : [
files('optimization_test.py'),
'--test-runner', glsl_test
],
suite : ['compiler', 'glsl'],
)
endif
if with_tools.contains('glsl')

View file

@ -1,125 +0,0 @@
# encoding=utf-8
# Copyright © 2018 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 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.
"""Script to generate and run glsl optimization tests."""
import argparse
import difflib
import errno
import os
import subprocess
import sys
import sexps
import lower_jump_cases
# The meson version handles windows paths better, but if it's not available
# fall back to shlex
try:
from meson.mesonlib import split_args
except ImportError:
from shlex import split as split_args
def arg_parser():
parser = argparse.ArgumentParser()
parser.add_argument(
'--test-runner',
required=True,
help='The glsl_test binary.')
return parser.parse_args()
def compare(actual, expected):
"""Compare the s-expresions and return a diff if they are different."""
actual = sexps.sort_decls(sexps.parse_sexp(actual))
expected = sexps.sort_decls(sexps.parse_sexp(expected))
if actual == expected:
return None
actual = sexps.sexp_to_string(actual)
expected = sexps.sexp_to_string(expected)
return difflib.unified_diff(expected.splitlines(), actual.splitlines())
def get_test_runner(runner):
"""Wrap the test runner in the exe wrapper if necessary."""
wrapper = os.environ.get('MESON_EXE_WRAPPER', None)
if wrapper is None:
return [runner]
return split_args(wrapper) + [runner]
def main():
"""Generate each test and report pass or fail."""
args = arg_parser()
total = 0
passes = 0
runner = get_test_runner(args.test_runner)
for gen in lower_jump_cases.CASES:
for name, opt, source, expected in gen():
total += 1
print('{}: '.format(name), end='')
proc = subprocess.Popen(
runner + ['optpass', '--quiet', '--input-ir', opt],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
stdin=subprocess.PIPE)
out, err = proc.communicate(source.encode('utf-8'))
out = out.decode('utf-8')
err = err.decode('utf-8')
if proc.returncode == 255:
print("Test returned general error, possibly missing linker")
sys.exit(77)
if err:
print('FAIL')
print('Unexpected output on stderr: {}'.format(err),
file=sys.stdout)
continue
result = compare(out, expected)
if result is not None:
print('FAIL')
for l in result:
print(l, file=sys.stderr)
else:
print('PASS')
passes += 1
print('{}/{} tests returned correct results'.format(passes, total))
exit(0 if passes == total else 1)
if __name__ == '__main__':
try:
main()
except OSError as e:
if e.errno == errno.ENOEXEC:
print('Skipping due to inability to run host binaries', file=sys.stderr)
sys.exit(77)
raise

View file

@ -1,103 +0,0 @@
# 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.
# This file contains helper functions for manipulating sexps in Python.
#
# We represent a sexp in Python using nested lists containing strings.
# So, for example, the sexp (constant float (1.000000)) is represented
# as ['constant', 'float', ['1.000000']].
import re
def check_sexp(sexp):
"""Verify that the argument is a proper sexp.
That is, raise an exception if the argument is not a string or a
list, or if it contains anything that is not a string or a list at
any nesting level.
"""
if isinstance(sexp, list):
for s in sexp:
check_sexp(s)
elif not isinstance(sexp, str):
raise Exception('Not a sexp: {0!r}'.format(sexp))
def parse_sexp(sexp):
"""Convert a string, of the form that would be output by mesa,
into a sexp represented as nested lists containing strings.
"""
sexp_token_regexp = re.compile(
'[a-zA-Z_]+(@[0-9]+)?|[0-9]+(\\.[0-9]+)?|[^ \r?\n]')
stack = [[]]
for match in sexp_token_regexp.finditer(sexp):
token = match.group(0)
if token == '(':
stack.append([])
elif token == ')':
if len(stack) == 1:
raise Exception('Unmatched )')
sexp = stack.pop()
stack[-1].append(sexp)
else:
stack[-1].append(token)
if len(stack) != 1:
raise Exception('Unmatched (')
if len(stack[0]) != 1:
raise Exception('Multiple sexps')
return stack[0][0]
def sexp_to_string(sexp):
"""Convert a sexp, represented as nested lists containing strings,
into a single string of the form parseable by mesa.
"""
if isinstance(sexp, str):
return sexp
assert isinstance(sexp, list)
result = ''
for s in sexp:
sub_result = sexp_to_string(s)
if result == '':
result = sub_result
elif '\n' not in result and '\n' not in sub_result and \
len(result) + len(sub_result) + 1 <= 70:
result += ' ' + sub_result
else:
result += '\n' + sub_result
return '({0})'.format(result.replace('\n', '\n '))
def sort_decls(sexp):
"""Sort all toplevel variable declarations in sexp.
This is used to work around the fact that
ir_reader::read_instructions reorders declarations.
"""
assert isinstance(sexp, list)
decls = []
other_code = []
for s in sexp:
if isinstance(s, list) and len(s) >= 4 and s[0] == 'declare':
decls.append(s)
else:
other_code.append(s)
return sorted(decls) + other_code