1*82d56013Sjoerg#!/usr/bin/env python3 27330f729Sjoerg 37330f729Sjoerg"""Updates FileCheck checks in MIR tests. 47330f729Sjoerg 57330f729SjoergThis script is a utility to update MIR based tests with new FileCheck 67330f729Sjoergpatterns. 77330f729Sjoerg 87330f729SjoergThe checks added by this script will cover the entire body of each 97330f729Sjoergfunction it handles. Virtual registers used are given names via 107330f729SjoergFileCheck patterns, so if you do want to check a subset of the body it 117330f729Sjoergshould be straightforward to trim out the irrelevant parts. None of 127330f729Sjoergthe YAML metadata will be checked, other than function names. 137330f729Sjoerg 147330f729SjoergIf there are multiple llc commands in a test, the full set of checks 157330f729Sjoergwill be repeated for each different check pattern. Checks for patterns 167330f729Sjoergthat are common between different commands will be left as-is by 177330f729Sjoergdefault, or removed if the --remove-common-prefixes flag is provided. 187330f729Sjoerg""" 197330f729Sjoerg 207330f729Sjoergfrom __future__ import print_function 217330f729Sjoerg 227330f729Sjoergimport argparse 237330f729Sjoergimport collections 247330f729Sjoergimport glob 257330f729Sjoergimport os 267330f729Sjoergimport re 277330f729Sjoergimport subprocess 287330f729Sjoergimport sys 297330f729Sjoerg 307330f729Sjoergfrom UpdateTestChecks import common 317330f729Sjoerg 327330f729SjoergMIR_FUNC_NAME_RE = re.compile(r' *name: *(?P<func>[A-Za-z0-9_.-]+)') 337330f729SjoergMIR_BODY_BEGIN_RE = re.compile(r' *body: *\|') 347330f729SjoergMIR_BASIC_BLOCK_RE = re.compile(r' *bb\.[0-9]+.*:$') 357330f729SjoergVREG_RE = re.compile(r'(%[0-9]+)(?::[a-z0-9_]+)?(?:\([<>a-z0-9 ]+\))?') 367330f729SjoergMI_FLAGS_STR= ( 377330f729Sjoerg r'(frame-setup |frame-destroy |nnan |ninf |nsz |arcp |contract |afn ' 387330f729Sjoerg r'|reassoc |nuw |nsw |exact |fpexcept )*') 397330f729SjoergVREG_DEF_RE = re.compile( 407330f729Sjoerg r'^ *(?P<vregs>{0}(?:, {0})*) = ' 417330f729Sjoerg r'{1}(?P<opcode>[A-Zt][A-Za-z0-9_]+)'.format(VREG_RE.pattern, MI_FLAGS_STR)) 427330f729SjoergMIR_PREFIX_DATA_RE = re.compile(r'^ *(;|bb.[0-9].*: *$|[a-z]+:( |$)|$)') 437330f729Sjoerg 447330f729SjoergIR_FUNC_NAME_RE = re.compile( 457330f729Sjoerg r'^\s*define\s+(?:internal\s+)?[^@]*@(?P<func>[A-Za-z0-9_.]+)\s*\(') 467330f729SjoergIR_PREFIX_DATA_RE = re.compile(r'^ *(;|$)') 477330f729Sjoerg 487330f729SjoergMIR_FUNC_RE = re.compile( 497330f729Sjoerg r'^---$' 507330f729Sjoerg r'\n' 517330f729Sjoerg r'^ *name: *(?P<func>[A-Za-z0-9_.-]+)$' 527330f729Sjoerg r'.*?' 537330f729Sjoerg r'^ *body: *\|\n' 547330f729Sjoerg r'(?P<body>.*?)\n' 557330f729Sjoerg r'^\.\.\.$', 567330f729Sjoerg flags=(re.M | re.S)) 577330f729Sjoerg 587330f729Sjoerg 597330f729Sjoergclass LLC: 607330f729Sjoerg def __init__(self, bin): 617330f729Sjoerg self.bin = bin 627330f729Sjoerg 637330f729Sjoerg def __call__(self, args, ir): 647330f729Sjoerg if ir.endswith('.mir'): 657330f729Sjoerg args = '{} -x mir'.format(args) 667330f729Sjoerg with open(ir) as ir_file: 677330f729Sjoerg stdout = subprocess.check_output('{} {}'.format(self.bin, args), 687330f729Sjoerg shell=True, stdin=ir_file) 697330f729Sjoerg if sys.version_info[0] > 2: 707330f729Sjoerg stdout = stdout.decode() 717330f729Sjoerg # Fix line endings to unix CR style. 727330f729Sjoerg stdout = stdout.replace('\r\n', '\n') 737330f729Sjoerg return stdout 747330f729Sjoerg 757330f729Sjoerg 767330f729Sjoergclass Run: 777330f729Sjoerg def __init__(self, prefixes, cmd_args, triple): 787330f729Sjoerg self.prefixes = prefixes 797330f729Sjoerg self.cmd_args = cmd_args 807330f729Sjoerg self.triple = triple 817330f729Sjoerg 827330f729Sjoerg def __getitem__(self, index): 837330f729Sjoerg return [self.prefixes, self.cmd_args, self.triple][index] 847330f729Sjoerg 857330f729Sjoerg 867330f729Sjoergdef log(msg, verbose=True): 877330f729Sjoerg if verbose: 887330f729Sjoerg print(msg, file=sys.stderr) 897330f729Sjoerg 907330f729Sjoerg 917330f729Sjoergdef find_triple_in_ir(lines, verbose=False): 927330f729Sjoerg for l in lines: 937330f729Sjoerg m = common.TRIPLE_IR_RE.match(l) 947330f729Sjoerg if m: 957330f729Sjoerg return m.group(1) 967330f729Sjoerg return None 977330f729Sjoerg 987330f729Sjoerg 997330f729Sjoergdef build_run_list(test, run_lines, verbose=False): 1007330f729Sjoerg run_list = [] 1017330f729Sjoerg all_prefixes = [] 1027330f729Sjoerg for l in run_lines: 1037330f729Sjoerg if '|' not in l: 1047330f729Sjoerg common.warn('Skipping unparseable RUN line: ' + l) 1057330f729Sjoerg continue 1067330f729Sjoerg 1077330f729Sjoerg commands = [cmd.strip() for cmd in l.split('|', 1)] 1087330f729Sjoerg llc_cmd = commands[0] 1097330f729Sjoerg filecheck_cmd = commands[1] if len(commands) > 1 else '' 1107330f729Sjoerg common.verify_filecheck_prefixes(filecheck_cmd) 1117330f729Sjoerg 1127330f729Sjoerg if not llc_cmd.startswith('llc '): 1137330f729Sjoerg common.warn('Skipping non-llc RUN line: {}'.format(l), test_file=test) 1147330f729Sjoerg continue 1157330f729Sjoerg if not filecheck_cmd.startswith('FileCheck '): 1167330f729Sjoerg common.warn('Skipping non-FileChecked RUN line: {}'.format(l), 1177330f729Sjoerg test_file=test) 1187330f729Sjoerg continue 1197330f729Sjoerg 1207330f729Sjoerg triple = None 1217330f729Sjoerg m = common.TRIPLE_ARG_RE.search(llc_cmd) 1227330f729Sjoerg if m: 1237330f729Sjoerg triple = m.group(1) 1247330f729Sjoerg # If we find -march but not -mtriple, use that. 1257330f729Sjoerg m = common.MARCH_ARG_RE.search(llc_cmd) 1267330f729Sjoerg if m and not triple: 1277330f729Sjoerg triple = '{}--'.format(m.group(1)) 1287330f729Sjoerg 1297330f729Sjoerg cmd_args = llc_cmd[len('llc'):].strip() 1307330f729Sjoerg cmd_args = cmd_args.replace('< %s', '').replace('%s', '').strip() 1317330f729Sjoerg 1327330f729Sjoerg check_prefixes = [ 1337330f729Sjoerg item 1347330f729Sjoerg for m in common.CHECK_PREFIX_RE.finditer(filecheck_cmd) 1357330f729Sjoerg for item in m.group(1).split(',')] 1367330f729Sjoerg if not check_prefixes: 1377330f729Sjoerg check_prefixes = ['CHECK'] 1387330f729Sjoerg all_prefixes += check_prefixes 1397330f729Sjoerg 1407330f729Sjoerg run_list.append(Run(check_prefixes, cmd_args, triple)) 1417330f729Sjoerg 1427330f729Sjoerg # Remove any common prefixes. We'll just leave those entirely alone. 1437330f729Sjoerg common_prefixes = set([prefix for prefix in all_prefixes 1447330f729Sjoerg if all_prefixes.count(prefix) > 1]) 1457330f729Sjoerg for run in run_list: 1467330f729Sjoerg run.prefixes = [p for p in run.prefixes if p not in common_prefixes] 1477330f729Sjoerg 1487330f729Sjoerg return run_list, common_prefixes 1497330f729Sjoerg 1507330f729Sjoerg 1517330f729Sjoergdef find_functions_with_one_bb(lines, verbose=False): 1527330f729Sjoerg result = [] 1537330f729Sjoerg cur_func = None 1547330f729Sjoerg bbs = 0 1557330f729Sjoerg for line in lines: 1567330f729Sjoerg m = MIR_FUNC_NAME_RE.match(line) 1577330f729Sjoerg if m: 1587330f729Sjoerg if bbs == 1: 1597330f729Sjoerg result.append(cur_func) 1607330f729Sjoerg cur_func = m.group('func') 1617330f729Sjoerg bbs = 0 1627330f729Sjoerg m = MIR_BASIC_BLOCK_RE.match(line) 1637330f729Sjoerg if m: 1647330f729Sjoerg bbs += 1 1657330f729Sjoerg if bbs == 1: 1667330f729Sjoerg result.append(cur_func) 1677330f729Sjoerg return result 1687330f729Sjoerg 1697330f729Sjoerg 1707330f729Sjoergdef build_function_body_dictionary(test, raw_tool_output, triple, prefixes, 1717330f729Sjoerg func_dict, verbose): 1727330f729Sjoerg for m in MIR_FUNC_RE.finditer(raw_tool_output): 1737330f729Sjoerg func = m.group('func') 1747330f729Sjoerg body = m.group('body') 1757330f729Sjoerg if verbose: 1767330f729Sjoerg log('Processing function: {}'.format(func)) 1777330f729Sjoerg for l in body.splitlines(): 1787330f729Sjoerg log(' {}'.format(l)) 1797330f729Sjoerg for prefix in prefixes: 1807330f729Sjoerg if func in func_dict[prefix] and func_dict[prefix][func] != body: 1817330f729Sjoerg common.warn('Found conflicting asm for prefix: {}'.format(prefix), 1827330f729Sjoerg test_file=test) 1837330f729Sjoerg func_dict[prefix][func] = body 1847330f729Sjoerg 1857330f729Sjoerg 1867330f729Sjoergdef add_checks_for_function(test, output_lines, run_list, func_dict, func_name, 1877330f729Sjoerg single_bb, verbose=False): 1887330f729Sjoerg printed_prefixes = set() 1897330f729Sjoerg for run in run_list: 1907330f729Sjoerg for prefix in run.prefixes: 1917330f729Sjoerg if prefix in printed_prefixes: 1927330f729Sjoerg continue 1937330f729Sjoerg if not func_dict[prefix][func_name]: 1947330f729Sjoerg continue 1957330f729Sjoerg # if printed_prefixes: 1967330f729Sjoerg # # Add some space between different check prefixes. 1977330f729Sjoerg # output_lines.append('') 1987330f729Sjoerg printed_prefixes.add(prefix) 1997330f729Sjoerg log('Adding {} lines for {}'.format(prefix, func_name), verbose) 2007330f729Sjoerg add_check_lines(test, output_lines, prefix, func_name, single_bb, 2017330f729Sjoerg func_dict[prefix][func_name].splitlines()) 2027330f729Sjoerg break 2037330f729Sjoerg return output_lines 2047330f729Sjoerg 2057330f729Sjoerg 2067330f729Sjoergdef add_check_lines(test, output_lines, prefix, func_name, single_bb, 2077330f729Sjoerg func_body): 2087330f729Sjoerg if single_bb: 2097330f729Sjoerg # Don't bother checking the basic block label for a single BB 2107330f729Sjoerg func_body.pop(0) 2117330f729Sjoerg 2127330f729Sjoerg if not func_body: 2137330f729Sjoerg common.warn('Function has no instructions to check: {}'.format(func_name), 2147330f729Sjoerg test_file=test) 2157330f729Sjoerg return 2167330f729Sjoerg 2177330f729Sjoerg first_line = func_body[0] 2187330f729Sjoerg indent = len(first_line) - len(first_line.lstrip(' ')) 2197330f729Sjoerg # A check comment, indented the appropriate amount 2207330f729Sjoerg check = '{:>{}}; {}'.format('', indent, prefix) 2217330f729Sjoerg 2227330f729Sjoerg output_lines.append('{}-LABEL: name: {}'.format(check, func_name)) 2237330f729Sjoerg 2247330f729Sjoerg vreg_map = {} 2257330f729Sjoerg for func_line in func_body: 2267330f729Sjoerg if not func_line.strip(): 2277330f729Sjoerg continue 2287330f729Sjoerg m = VREG_DEF_RE.match(func_line) 2297330f729Sjoerg if m: 2307330f729Sjoerg for vreg in VREG_RE.finditer(m.group('vregs')): 2317330f729Sjoerg name = mangle_vreg(m.group('opcode'), vreg_map.values()) 2327330f729Sjoerg vreg_map[vreg.group(1)] = name 2337330f729Sjoerg func_line = func_line.replace( 2347330f729Sjoerg vreg.group(1), '[[{}:%[0-9]+]]'.format(name), 1) 2357330f729Sjoerg for number, name in vreg_map.items(): 2367330f729Sjoerg func_line = re.sub(r'{}\b'.format(number), '[[{}]]'.format(name), 2377330f729Sjoerg func_line) 2387330f729Sjoerg check_line = '{}: {}'.format(check, func_line[indent:]).rstrip() 2397330f729Sjoerg output_lines.append(check_line) 2407330f729Sjoerg 2417330f729Sjoerg 2427330f729Sjoergdef mangle_vreg(opcode, current_names): 2437330f729Sjoerg base = opcode 2447330f729Sjoerg # Simplify some common prefixes and suffixes 2457330f729Sjoerg if opcode.startswith('G_'): 2467330f729Sjoerg base = base[len('G_'):] 2477330f729Sjoerg if opcode.endswith('_PSEUDO'): 2487330f729Sjoerg base = base[:len('_PSEUDO')] 2497330f729Sjoerg # Shorten some common opcodes with long-ish names 2507330f729Sjoerg base = dict(IMPLICIT_DEF='DEF', 2517330f729Sjoerg GLOBAL_VALUE='GV', 2527330f729Sjoerg CONSTANT='C', 2537330f729Sjoerg FCONSTANT='C', 2547330f729Sjoerg MERGE_VALUES='MV', 2557330f729Sjoerg UNMERGE_VALUES='UV', 2567330f729Sjoerg INTRINSIC='INT', 2577330f729Sjoerg INTRINSIC_W_SIDE_EFFECTS='INT', 2587330f729Sjoerg INSERT_VECTOR_ELT='IVEC', 2597330f729Sjoerg EXTRACT_VECTOR_ELT='EVEC', 2607330f729Sjoerg SHUFFLE_VECTOR='SHUF').get(base, base) 2617330f729Sjoerg # Avoid ambiguity when opcodes end in numbers 2627330f729Sjoerg if len(base.rstrip('0123456789')) < len(base): 2637330f729Sjoerg base += '_' 2647330f729Sjoerg 2657330f729Sjoerg i = 0 2667330f729Sjoerg for name in current_names: 2677330f729Sjoerg if name.rstrip('0123456789') == base: 2687330f729Sjoerg i += 1 2697330f729Sjoerg if i: 2707330f729Sjoerg return '{}{}'.format(base, i) 2717330f729Sjoerg return base 2727330f729Sjoerg 2737330f729Sjoerg 2747330f729Sjoergdef should_add_line_to_output(input_line, prefix_set): 2757330f729Sjoerg # Skip any check lines that we're handling. 2767330f729Sjoerg m = common.CHECK_RE.match(input_line) 2777330f729Sjoerg if m and m.group(1) in prefix_set: 2787330f729Sjoerg return False 2797330f729Sjoerg return True 2807330f729Sjoerg 2817330f729Sjoerg 2827330f729Sjoergdef update_test_file(args, test): 2837330f729Sjoerg with open(test) as fd: 2847330f729Sjoerg input_lines = [l.rstrip() for l in fd] 2857330f729Sjoerg 2867330f729Sjoerg script_name = os.path.basename(__file__) 2877330f729Sjoerg first_line = input_lines[0] if input_lines else "" 2887330f729Sjoerg if 'autogenerated' in first_line and script_name not in first_line: 2897330f729Sjoerg common.warn("Skipping test which wasn't autogenerated by " + 2907330f729Sjoerg script_name + ": " + test) 2917330f729Sjoerg return 2927330f729Sjoerg 2937330f729Sjoerg if args.update_only: 2947330f729Sjoerg if not first_line or 'autogenerated' not in first_line: 2957330f729Sjoerg common.warn("Skipping test which isn't autogenerated: " + test) 2967330f729Sjoerg return 2977330f729Sjoerg 2987330f729Sjoerg triple_in_ir = find_triple_in_ir(input_lines, args.verbose) 299*82d56013Sjoerg run_lines = common.find_run_lines(test, input_lines) 3007330f729Sjoerg run_list, common_prefixes = build_run_list(test, run_lines, args.verbose) 3017330f729Sjoerg 3027330f729Sjoerg simple_functions = find_functions_with_one_bb(input_lines, args.verbose) 3037330f729Sjoerg 3047330f729Sjoerg func_dict = {} 3057330f729Sjoerg for run in run_list: 3067330f729Sjoerg for prefix in run.prefixes: 3077330f729Sjoerg func_dict.update({prefix: dict()}) 3087330f729Sjoerg for prefixes, llc_args, triple_in_cmd in run_list: 3097330f729Sjoerg log('Extracted LLC cmd: llc {}'.format(llc_args), args.verbose) 3107330f729Sjoerg log('Extracted FileCheck prefixes: {}'.format(prefixes), args.verbose) 3117330f729Sjoerg 3127330f729Sjoerg raw_tool_output = args.llc(llc_args, test) 3137330f729Sjoerg if not triple_in_cmd and not triple_in_ir: 3147330f729Sjoerg common.warn('No triple found: skipping file', test_file=test) 3157330f729Sjoerg return 3167330f729Sjoerg 3177330f729Sjoerg build_function_body_dictionary(test, raw_tool_output, 3187330f729Sjoerg triple_in_cmd or triple_in_ir, 3197330f729Sjoerg prefixes, func_dict, args.verbose) 3207330f729Sjoerg 3217330f729Sjoerg state = 'toplevel' 3227330f729Sjoerg func_name = None 3237330f729Sjoerg prefix_set = set([prefix for run in run_list for prefix in run.prefixes]) 3247330f729Sjoerg log('Rewriting FileCheck prefixes: {}'.format(prefix_set), args.verbose) 3257330f729Sjoerg 3267330f729Sjoerg if args.remove_common_prefixes: 3277330f729Sjoerg prefix_set.update(common_prefixes) 3287330f729Sjoerg elif common_prefixes: 3297330f729Sjoerg common.warn('Ignoring common prefixes: {}'.format(common_prefixes), 3307330f729Sjoerg test_file=test) 3317330f729Sjoerg 3327330f729Sjoerg comment_char = '#' if test.endswith('.mir') else ';' 3337330f729Sjoerg autogenerated_note = ('{} NOTE: Assertions have been autogenerated by ' 3347330f729Sjoerg 'utils/{}'.format(comment_char, script_name)) 3357330f729Sjoerg output_lines = [] 3367330f729Sjoerg output_lines.append(autogenerated_note) 3377330f729Sjoerg 3387330f729Sjoerg for input_line in input_lines: 3397330f729Sjoerg if input_line == autogenerated_note: 3407330f729Sjoerg continue 3417330f729Sjoerg 3427330f729Sjoerg if state == 'toplevel': 3437330f729Sjoerg m = IR_FUNC_NAME_RE.match(input_line) 3447330f729Sjoerg if m: 3457330f729Sjoerg state = 'ir function prefix' 3467330f729Sjoerg func_name = m.group('func') 3477330f729Sjoerg if input_line.rstrip('| \r\n') == '---': 3487330f729Sjoerg state = 'document' 3497330f729Sjoerg output_lines.append(input_line) 3507330f729Sjoerg elif state == 'document': 3517330f729Sjoerg m = MIR_FUNC_NAME_RE.match(input_line) 3527330f729Sjoerg if m: 3537330f729Sjoerg state = 'mir function metadata' 3547330f729Sjoerg func_name = m.group('func') 3557330f729Sjoerg if input_line.strip() == '...': 3567330f729Sjoerg state = 'toplevel' 3577330f729Sjoerg func_name = None 3587330f729Sjoerg if should_add_line_to_output(input_line, prefix_set): 3597330f729Sjoerg output_lines.append(input_line) 3607330f729Sjoerg elif state == 'mir function metadata': 3617330f729Sjoerg if should_add_line_to_output(input_line, prefix_set): 3627330f729Sjoerg output_lines.append(input_line) 3637330f729Sjoerg m = MIR_BODY_BEGIN_RE.match(input_line) 3647330f729Sjoerg if m: 3657330f729Sjoerg if func_name in simple_functions: 3667330f729Sjoerg # If there's only one block, put the checks inside it 3677330f729Sjoerg state = 'mir function prefix' 3687330f729Sjoerg continue 3697330f729Sjoerg state = 'mir function body' 3707330f729Sjoerg add_checks_for_function(test, output_lines, run_list, 3717330f729Sjoerg func_dict, func_name, single_bb=False, 3727330f729Sjoerg verbose=args.verbose) 3737330f729Sjoerg elif state == 'mir function prefix': 3747330f729Sjoerg m = MIR_PREFIX_DATA_RE.match(input_line) 3757330f729Sjoerg if not m: 3767330f729Sjoerg state = 'mir function body' 3777330f729Sjoerg add_checks_for_function(test, output_lines, run_list, 3787330f729Sjoerg func_dict, func_name, single_bb=True, 3797330f729Sjoerg verbose=args.verbose) 3807330f729Sjoerg 3817330f729Sjoerg if should_add_line_to_output(input_line, prefix_set): 3827330f729Sjoerg output_lines.append(input_line) 3837330f729Sjoerg elif state == 'mir function body': 3847330f729Sjoerg if input_line.strip() == '...': 3857330f729Sjoerg state = 'toplevel' 3867330f729Sjoerg func_name = None 3877330f729Sjoerg if should_add_line_to_output(input_line, prefix_set): 3887330f729Sjoerg output_lines.append(input_line) 3897330f729Sjoerg elif state == 'ir function prefix': 3907330f729Sjoerg m = IR_PREFIX_DATA_RE.match(input_line) 3917330f729Sjoerg if not m: 3927330f729Sjoerg state = 'ir function body' 3937330f729Sjoerg add_checks_for_function(test, output_lines, run_list, 3947330f729Sjoerg func_dict, func_name, single_bb=False, 3957330f729Sjoerg verbose=args.verbose) 3967330f729Sjoerg 3977330f729Sjoerg if should_add_line_to_output(input_line, prefix_set): 3987330f729Sjoerg output_lines.append(input_line) 3997330f729Sjoerg elif state == 'ir function body': 4007330f729Sjoerg if input_line.strip() == '}': 4017330f729Sjoerg state = 'toplevel' 4027330f729Sjoerg func_name = None 4037330f729Sjoerg if should_add_line_to_output(input_line, prefix_set): 4047330f729Sjoerg output_lines.append(input_line) 4057330f729Sjoerg 4067330f729Sjoerg 4077330f729Sjoerg log('Writing {} lines to {}...'.format(len(output_lines), test), args.verbose) 4087330f729Sjoerg 4097330f729Sjoerg with open(test, 'wb') as fd: 4107330f729Sjoerg fd.writelines(['{}\n'.format(l).encode('utf-8') for l in output_lines]) 4117330f729Sjoerg 4127330f729Sjoerg 4137330f729Sjoergdef main(): 4147330f729Sjoerg parser = argparse.ArgumentParser( 4157330f729Sjoerg description=__doc__, formatter_class=argparse.RawTextHelpFormatter) 4167330f729Sjoerg parser.add_argument('--llc-binary', dest='llc', default='llc', type=LLC, 4177330f729Sjoerg help='The "llc" binary to generate the test case with') 4187330f729Sjoerg parser.add_argument('--remove-common-prefixes', action='store_true', 4197330f729Sjoerg help='Remove existing check lines whose prefixes are ' 4207330f729Sjoerg 'shared between multiple commands') 4217330f729Sjoerg parser.add_argument('tests', nargs='+') 422*82d56013Sjoerg args = common.parse_commandline_args(parser) 4237330f729Sjoerg 4247330f729Sjoerg test_paths = [test for pattern in args.tests for test in glob.glob(pattern)] 4257330f729Sjoerg for test in test_paths: 4267330f729Sjoerg try: 4277330f729Sjoerg update_test_file(args, test) 4287330f729Sjoerg except Exception: 4297330f729Sjoerg common.warn('Error processing file', test_file=test) 4307330f729Sjoerg raise 4317330f729Sjoerg 4327330f729Sjoerg 4337330f729Sjoergif __name__ == '__main__': 4347330f729Sjoerg main() 435