diff options
Diffstat (limited to 'llvm/utils/UpdateTestChecks/common.py')
-rw-r--r-- | llvm/utils/UpdateTestChecks/common.py | 58 |
1 files changed, 45 insertions, 13 deletions
diff --git a/llvm/utils/UpdateTestChecks/common.py b/llvm/utils/UpdateTestChecks/common.py index 90dd326..7ca546c 100644 --- a/llvm/utils/UpdateTestChecks/common.py +++ b/llvm/utils/UpdateTestChecks/common.py @@ -10,6 +10,8 @@ import subprocess import sys import shlex +from typing import List + ##### Common utilities for update_*test_checks.py @@ -129,6 +131,11 @@ def parse_commandline_args(parser): help='List of regular expressions that a global value declaration must match to generate a check (has no effect if checking globals is not enabled)') parser.add_argument('--global-hex-value-regex', nargs='+', default=[], help='List of regular expressions such that, for matching global value declarations, literal integer values should be encoded in hex in the associated FileCheck directives') + parser.add_argument('--generate-body-for-unused-prefixes', + action=argparse.BooleanOptionalAction, + dest='gen_unused_prefix_body', + default=True, + help='Generate a function body that always matches for unused prefixes. This is useful when unused prefixes are desired, and it avoids needing to annotate each FileCheck as allowing them.') args = parser.parse_args() global _verbose, _global_value_regex, _global_hex_value_regex _verbose = args.verbose @@ -167,6 +174,7 @@ class TestInfo(object): self.autogenerated_note_prefix = self.comment_prefix + ' ' + UTC_ADVERT self.test_autogenerated_note = self.autogenerated_note_prefix + script_name self.test_autogenerated_note += get_autogennote_suffix(parser, self.args) + self.test_unused_note = self.comment_prefix + self.comment_prefix + ' ' + UNUSED_NOTE def ro_iterlines(self): for line_num, input_line in enumerate(self.input_lines): @@ -188,6 +196,22 @@ class TestInfo(object): continue yield line_info + def get_checks_for_unused_prefixes(self, run_list, used_prefixes: List[str]) -> List[str]: + unused_prefixes = set( + [prefix for sublist in run_list for prefix in sublist[0]]).difference(set(used_prefixes)) + + ret = [] + if not unused_prefixes: + return ret + ret.append(self.test_unused_note) + for unused in sorted(unused_prefixes): + ret.append('{comment} {prefix}: {match_everything}'.format( + comment=self.comment_prefix, + prefix=unused, + match_everything=r"""{{.*}}""" + )) + return ret + def itertests(test_patterns, parser, script_name, comment_prefix=None, argparse_callback=None): for pattern in test_patterns: # On Windows we must expand the patterns ourselves. @@ -212,7 +236,12 @@ def itertests(test_patterns, parser, script_name, comment_prefix=None, argparse_ assert UTC_ADVERT not in first_line warn("Skipping test which isn't autogenerated: " + test) continue - yield TestInfo(test, parser, script_name, input_lines, args, argv, + final_input_lines = [] + for l in input_lines: + if UNUSED_NOTE in l: + break + final_input_lines.append(l) + yield TestInfo(test, parser, script_name, final_input_lines, args, argv, comment_prefix, argparse_callback) @@ -293,6 +322,7 @@ CHECK_RE = re.compile(r'^\s*(?://|[;#])\s*([^:]+?)(?:-NEXT|-NOT|-DAG|-LABEL|-SAM UTC_ARGS_KEY = 'UTC_ARGS:' UTC_ARGS_CMD = re.compile(r'.*' + UTC_ARGS_KEY + '\s*(?P<cmd>.*)\s*$') UTC_ADVERT = 'NOTE: Assertions have been autogenerated by ' +UNUSED_NOTE = 'NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:' OPT_FUNCTION_RE = re.compile( r'^(\s*;\s*Function\sAttrs:\s(?P<attrs>[\w\s]+?))?\s*define\s+(?:internal\s+)?[^@]*@(?P<func>[\w.$-]+?)\s*' @@ -471,7 +501,7 @@ class FunctionTestBuilder: self._global_var_dict.update({prefix:dict()}) def finish_and_get_func_dict(self): - for prefix in self._get_failed_prefixes(): + for prefix in self.get_failed_prefixes(): warn('Prefix %s had conflicting output from different RUN lines for all functions in test %s' % (prefix,self._path,)) return self._func_dict @@ -577,11 +607,10 @@ class FunctionTestBuilder: scrubbed_body, scrubbed_extra, args_and_sig, attrs, func_name_separator) self._func_order[prefix].append(func) - def _get_failed_prefixes(self): + def get_failed_prefixes(self): # This returns the list of those prefixes that failed to match any function, # because there were conflicting bodies produced by different RUN lines, in - # all instances of the prefix. Effectively, this prefix is unused and should - # be removed. + # all instances of the prefix. for prefix in self._func_dict: if (self._func_dict[prefix] and (not [fct for fct in self._func_dict[prefix] @@ -974,6 +1003,7 @@ def add_checks(output_lines, comment_marker, prefix_list, func_dict, func_name, if key not in global_vars_seen_before: global_vars_seen_dict[checkprefix][key] = global_vars_seen[key] break + return printed_prefixes def add_ir_checks(output_lines, comment_marker, prefix_list, func_dict, func_name, preserve_names, function_sig, @@ -981,16 +1011,16 @@ def add_ir_checks(output_lines, comment_marker, prefix_list, func_dict, # Label format is based on IR string. function_def_regex = 'define {{[^@]+}}' if function_sig else '' check_label_format = '{} %s-LABEL: {}@%s%s%s'.format(comment_marker, function_def_regex) - add_checks(output_lines, comment_marker, prefix_list, func_dict, func_name, - check_label_format, False, preserve_names, global_vars_seen_dict, - is_filtered) + return add_checks(output_lines, comment_marker, prefix_list, func_dict, func_name, + check_label_format, False, preserve_names, global_vars_seen_dict, + is_filtered) def add_analyze_checks(output_lines, comment_marker, prefix_list, func_dict, func_name, is_filtered): check_label_format = '{} %s-LABEL: \'%s%s%s\''.format(comment_marker) global_vars_seen_dict = {} - add_checks(output_lines, comment_marker, prefix_list, func_dict, func_name, - check_label_format, False, True, global_vars_seen_dict, - is_filtered) + return add_checks(output_lines, comment_marker, prefix_list, func_dict, func_name, + check_label_format, False, True, global_vars_seen_dict, + is_filtered) def build_global_values_dictionary(glob_val_dict, raw_tool_output, prefixes): for nameless_value in itertools.chain(ir_nameless_values, asm_nameless_values): @@ -1189,6 +1219,7 @@ def dump_input_lines(output_lines, test_info, prefix_set, comment_string): def add_checks_at_end(output_lines, prefix_list, func_order, comment_string, check_generator): added = set() + generated_prefixes = [] for prefix in prefix_list: prefixes = prefix[0] tool_args = prefix[1] @@ -1212,6 +1243,7 @@ def add_checks_at_end(output_lines, prefix_list, func_order, # single prefix before moving on to the next prefix. So checks # are ordered by prefix instead of by function as in "normal" # mode. - check_generator(output_lines, + generated_prefixes.extend(check_generator(output_lines, [([prefix], tool_args)], - func) + func)) + return generated_prefixes |