aboutsummaryrefslogtreecommitdiff
path: root/llvm/utils/UpdateTestChecks/common.py
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/utils/UpdateTestChecks/common.py')
-rw-r--r--llvm/utils/UpdateTestChecks/common.py58
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