blob: 68a49785889efe64c052f7c3f405c072cccf4fb8 [file] [log] [blame]
Antonio Maioranocf47d612022-10-04 19:48:41 +00001#!/usr/bin/env python3
2
Austin Engcc2516a2023-10-17 20:57:54 +00003# Copyright 2021 The Dawn & Tint Authors
Antonio Maioranocf47d612022-10-04 19:48:41 +00004#
Austin Engcc2516a2023-10-17 20:57:54 +00005# Redistribution and use in source and binary forms, with or without
6# modification, are permitted provided that the following conditions are met:
Antonio Maioranocf47d612022-10-04 19:48:41 +00007#
Austin Engcc2516a2023-10-17 20:57:54 +00008# 1. Redistributions of source code must retain the above copyright notice, this
9# list of conditions and the following disclaimer.
Antonio Maioranocf47d612022-10-04 19:48:41 +000010#
Austin Engcc2516a2023-10-17 20:57:54 +000011# 2. Redistributions in binary form must reproduce the above copyright notice,
12# this list of conditions and the following disclaimer in the documentation
13# and/or other materials provided with the distribution.
14#
15# 3. Neither the name of the copyright holder nor the names of its
16# contributors may be used to endorse or promote products derived from
17# this software without specific prior written permission.
18#
19# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Antonio Maioranocf47d612022-10-04 19:48:41 +000029
30# Parses expected.*.hlsl files for errors and outputs a report.
31#
32# Usage:
33# parse_hlsl_erors
34
35import glob
36import re
37import argparse
38
39parser = argparse.ArgumentParser()
40parser.add_argument('--list-files', dest='list_files', action='store_true')
41parser.add_argument('--no-list-files', dest='list_files', action='store_false')
42parser.set_defaults(list_files=True)
Antonio Maiorano9f7ab422024-09-18 21:13:34 +000043parser.add_argument('--ir-only', dest='ir_only', action='store_false')
44parser.set_defaults(ir_only=False)
Antonio Maioranocf47d612022-10-04 19:48:41 +000045args = parser.parse_args()
46
Antonio Maiorano9f7ab422024-09-18 21:13:34 +000047def add_error(error_to_files, error, file):
48 error = error.strip()
49 if not error in error_to_files:
50 error_to_files[error] = [file]
Antonio Maioranocf47d612022-10-04 19:48:41 +000051 else:
Antonio Maiorano9f7ab422024-09-18 21:13:34 +000052 error_to_files[error].append(file)
Antonio Maioranocf47d612022-10-04 19:48:41 +000053
Antonio Maiorano9f7ab422024-09-18 21:13:34 +000054def find_error(f, all_lines, error_to_files, is_fxc):
55 # Search for specific errors from top to bottom
56 for line in all_lines:
57 # Both
58 if line.startswith('test timed out after'):
59 add_error(error_to_files, line, f)
60 return True
61 if 'internal compiler error' in line:
62 add_error(error_to_files, line, f)
63 return True
64 if line.startswith('tint executable returned error:'):
65 add_error(error_to_files, line, f)
66 return True
67 m = re.search('Failed to generate:.*?(error:.*)', line)
68 if m:
69 add_error(error_to_files, m.groups()[0], f)
70 return True
71 # DXC
72 if not is_fxc:
73 if line.startswith('error: validation errors'):
74 continue # Skip line, next line should have better error
75
76 if line.startswith('error:'):
77 add_error(error_to_files, line, f)
78 return True
79
80 m = re.search('.*\.hlsl:[0-9]+:.*?(error.*)', line) # DXC???
81 if m:
82 add_error(error_to_files, m.groups()[0], f)
83 return True
84 # FXC
85 else:
86 if line.startswith('internal error:'):
87 add_error(error_to_files, line, f)
88 return True
89 m = re.search('error( X[0-9]+)+?:(.*)', line)
90 if m:
91 add_error(error_to_files, m.group(), f)
92 return True
93 return False
94
95
96def find_and_print_errors(glob_pathname, is_fxc):
Antonio Maioranocf47d612022-10-04 19:48:41 +000097 files = glob.glob(glob_pathname, recursive=True)
Antonio Maiorano9f7ab422024-09-18 21:13:34 +000098 error_to_files = {}
Antonio Maioranocf47d612022-10-04 19:48:41 +000099
100 for f in files:
101 found_error = False
102 with open(f, "r") as fs:
Antonio Maiorano71e72ee2023-08-30 14:48:24 +0000103 all_lines = fs.readlines()
104 first_line = all_lines[0]
Antonio Maiorano9f7ab422024-09-18 21:13:34 +0000105 if not first_line.startswith("SKIP:"): # Only process SKIPs
Antonio Maioranocf47d612022-10-04 19:48:41 +0000106 continue
Antonio Maiorano9f7ab422024-09-18 21:13:34 +0000107 if first_line.startswith("SKIP: INVALID"): # Except for INVALIDs
108 continue
109 found_error = find_error(f, all_lines, error_to_files, is_fxc)
Antonio Maioranocf47d612022-10-04 19:48:41 +0000110
111 if not found_error:
112 # If no error message was found, add the SKIP line as it may contain the reason for skipping
Antonio Maiorano9f7ab422024-09-18 21:13:34 +0000113 add_error(error_to_files, first_line, f)
Antonio Maioranocf47d612022-10-04 19:48:41 +0000114
Antonio Maiorano9f7ab422024-09-18 21:13:34 +0000115 for error,files in sorted(error_to_files.items()):
116 print('[{}] {} (count: {})'.format('fxc' if is_fxc else 'dxc', error, len(files)))
Antonio Maioranocf47d612022-10-04 19:48:41 +0000117 if args.list_files:
118 for f in files:
119 print('\t{}'.format(f))
120
Antonio Maioranocf47d612022-10-04 19:48:41 +0000121
Antonio Maiorano9f7ab422024-09-18 21:13:34 +0000122if args.ir_only:
123 print("=== FXC (IR only) ===")
124 find_and_print_errors('./**/*.ir.fxc.hlsl', is_fxc=True)
125 print("=== DXC (IR only) ===")
126 find_and_print_errors('./**/*.ir.dxc.hlsl', is_fxc=False)
127else:
128 print("=== FXC ===")
129 find_and_print_errors('./**/*.fxc.hlsl', is_fxc=True)
130 print("=== DXC ===")
131 find_and_print_errors('./**/*.dxc.hlsl', is_fxc=False)