diff options
Diffstat (limited to 'llvm/utils/UpdateTestChecks/common.py')
-rw-r--r-- | llvm/utils/UpdateTestChecks/common.py | 97 |
1 files changed, 70 insertions, 27 deletions
diff --git a/llvm/utils/UpdateTestChecks/common.py b/llvm/utils/UpdateTestChecks/common.py index d9be97c..c6553b1 100644 --- a/llvm/utils/UpdateTestChecks/common.py +++ b/llvm/utils/UpdateTestChecks/common.py @@ -3,6 +3,7 @@ from __future__ import print_function import argparse import copy import glob +import itertools import os import re import subprocess @@ -596,7 +597,7 @@ SCRUB_IR_COMMENT_RE = re.compile(r'\s*;.*') class NamelessValue: def __init__(self, check_prefix, check_key, ir_prefix, global_ir_prefix, global_ir_prefix_regexp, - ir_regexp, global_ir_rhs_regexp, is_before_functions): + ir_regexp, global_ir_rhs_regexp, is_before_functions, is_number=False): self.check_prefix = check_prefix self.check_key = check_key self.ir_prefix = ir_prefix @@ -605,6 +606,7 @@ class NamelessValue: self.ir_regexp = ir_regexp self.global_ir_rhs_regexp = global_ir_rhs_regexp self.is_before_functions = is_before_functions + self.is_number = is_number # Return true if this kind of IR value is "local", basically if it matches '%{{.*}}'. def is_local_def_ir_value_match(self, match): @@ -635,23 +637,29 @@ class NamelessValue: # for backwards compatibility we check locals with '.*' varname = get_value_name(var, self.check_prefix) prefix = self.get_ir_prefix_from_ir_value_match(match)[0] - regex = self.get_ir_regex_from_ir_value_re_match(match) + if self.is_number: + regex = '' # always capture a number in the default format + capture_start = '[[#' + else: + regex = self.get_ir_regex_from_ir_value_re_match(match) + capture_start = '[[' if self.is_local_def_ir_value_match(match): - return '[[' + varname + ':' + prefix + regex + ']]' - return prefix + '[[' + varname + ':' + regex + ']]' + return capture_start + varname + ':' + prefix + regex + ']]' + return prefix + capture_start + varname + ':' + regex + ']]' # Use a FileCheck variable. def get_value_use(self, var, match, var_prefix=None): if var_prefix is None: var_prefix = self.check_prefix + capture_start = '[[#' if self.is_number else '[[' if self.is_local_def_ir_value_match(match): - return '[[' + get_value_name(var, var_prefix) + ']]' + return capture_start + get_value_name(var, var_prefix) + ']]' prefix = self.get_ir_prefix_from_ir_value_match(match)[0] - return prefix + '[[' + get_value_name(var, var_prefix) + ']]' + return prefix + capture_start + get_value_name(var, var_prefix) + ']]' # Description of the different "unnamed" values we match in the IR, e.g., # (local) ssa values, (debug) metadata, etc. -nameless_values = [ +ir_nameless_values = [ NamelessValue(r'TMP' , '%' , r'%' , None , None , r'[\w$.-]+?' , None , False) , NamelessValue(r'ATTR' , '#' , r'#' , None , None , r'[0-9]+' , None , False) , NamelessValue(r'ATTR' , '#' , None , r'attributes #' , r'[0-9]+' , None , r'{[^}]*}' , False) , @@ -666,6 +674,11 @@ nameless_values = [ NamelessValue(r'META' , '!' , None , r'' , r'![0-9]+' , None , r'(?:distinct |)!.*' , False) , ] +asm_nameless_values = [ + NamelessValue(r'MCINST', 'Inst#', None, '<MCInst #', r'\d+', None, r'.+', False, True), + NamelessValue(r'MCREG', 'Reg:', None, '<MCOperand Reg:', r'\d+', None, r'.+', False, True), +] + def createOrRegexp(old, new): if not old: return new @@ -684,7 +697,7 @@ def createPrefixMatch(prefix_str, prefix_re): # other locations will need adjustment as well. IR_VALUE_REGEXP_PREFIX = r'(\s*)' IR_VALUE_REGEXP_STRING = r'' -for nameless_value in nameless_values: +for nameless_value in ir_nameless_values: lcl_match = createPrefixMatch(nameless_value.ir_prefix, nameless_value.ir_regexp) glb_match = createPrefixMatch(nameless_value.global_ir_prefix, nameless_value.global_ir_prefix_regexp) assert((lcl_match or glb_match) and not (lcl_match and glb_match)) @@ -695,6 +708,15 @@ for nameless_value in nameless_values: IR_VALUE_REGEXP_SUFFIX = r'([,\s\(\)]|\Z)' IR_VALUE_RE = re.compile(IR_VALUE_REGEXP_PREFIX + r'(' + IR_VALUE_REGEXP_STRING + r')' + IR_VALUE_REGEXP_SUFFIX) +# Build the regexp that matches an "ASM value" (currently only for --asm-show-inst comments). +ASM_VALUE_REGEXP_STRING = '' +for nameless_value in asm_nameless_values: + glb_match = createPrefixMatch(nameless_value.global_ir_prefix, nameless_value.global_ir_prefix_regexp) + assert not nameless_value.ir_prefix and not nameless_value.ir_regexp + ASM_VALUE_REGEXP_STRING = createOrRegexp(ASM_VALUE_REGEXP_STRING, glb_match) +ASM_VALUE_REGEXP_SUFFIX = r'([>\s]|\Z)' +ASM_VALUE_RE = re.compile(r'((?:#|//)\s*)' + '(' + ASM_VALUE_REGEXP_STRING + ')' + ASM_VALUE_REGEXP_SUFFIX) + # The entire match is group 0, the prefix has one group (=1), the entire # IR_VALUE_REGEXP_STRING is one group (=2), and then the nameless values start. first_nameless_group_in_ir_value_match = 3 @@ -738,7 +760,9 @@ def get_value_name(var, check_prefix): var = var.replace('-', '_') return var.upper() -def generalize_check_lines(lines, is_analyze, vars_seen, global_vars_seen): +def generalize_check_lines_common(lines, is_analyze, vars_seen, + global_vars_seen, nameless_values, + nameless_value_regex, is_asm): # This gets called for each match that occurs in # a line. We transform variables we haven't seen # into defs, and variables we have seen into uses. @@ -771,26 +795,38 @@ def generalize_check_lines(lines, is_analyze, vars_seen, global_vars_seen): lines_with_def = [] for i, line in enumerate(lines): - # An IR variable named '%.' matches the FileCheck regex string. - line = line.replace('%.', '%dot') - for regex in _global_hex_value_regex: - if re.match('^@' + regex + ' = ', line): - line = re.sub(r'\bi([0-9]+) ([0-9]+)', - lambda m : 'i' + m.group(1) + ' [[#' + hex(int(m.group(2))) + ']]', - line) - break - # Ignore any comments, since the check lines will too. - scrubbed_line = SCRUB_IR_COMMENT_RE.sub(r'', line) - lines[i] = scrubbed_line - if not is_analyze: + if not is_asm: + # An IR variable named '%.' matches the FileCheck regex string. + line = line.replace('%.', '%dot') + for regex in _global_hex_value_regex: + if re.match('^@' + regex + ' = ', line): + line = re.sub(r'\bi([0-9]+) ([0-9]+)', + lambda m : 'i' + m.group(1) + ' [[#' + hex(int(m.group(2))) + ']]', + line) + break + # Ignore any comments, since the check lines will too. + scrubbed_line = SCRUB_IR_COMMENT_RE.sub(r'', line) + lines[i] = scrubbed_line + if is_asm or not is_analyze: # It can happen that two matches are back-to-back and for some reason sub # will not replace both of them. For now we work around this by # substituting until there is no more match. changed = True while changed: - (lines[i], changed) = IR_VALUE_RE.subn(transform_line_vars, lines[i], count=1) + (lines[i], changed) = nameless_value_regex.subn(transform_line_vars, + lines[i], count=1) return lines +# Replace IR value defs and uses with FileCheck variables. +def generalize_check_lines(lines, is_analyze, vars_seen, global_vars_seen): + return generalize_check_lines_common(lines, is_analyze, vars_seen, + global_vars_seen, ir_nameless_values, + IR_VALUE_RE, False) + +def generalize_asm_check_lines(lines, vars_seen, global_vars_seen): + return generalize_check_lines_common(lines, False, vars_seen, + global_vars_seen, asm_nameless_values, + ASM_VALUE_RE, True) def add_checks(output_lines, comment_marker, prefix_list, func_dict, func_name, check_label_format, is_backend, is_analyze, global_vars_seen_dict, is_filtered): # prefix_exclusions are prefixes we cannot use to print the function because it doesn't exist in run lines that use these prefixes as well. @@ -843,7 +879,8 @@ def add_checks(output_lines, comment_marker, prefix_list, func_dict, func_name, if attrs: output_lines.append('%s %s: Function Attrs: %s' % (comment_marker, checkprefix, attrs)) args_and_sig = str(func_dict[checkprefix][func_name].args_and_sig) - args_and_sig = generalize_check_lines([args_and_sig], is_analyze, vars_seen, global_vars_seen)[0] + if args_and_sig: + args_and_sig = generalize_check_lines([args_and_sig], is_analyze, vars_seen, global_vars_seen)[0] func_name_separator = func_dict[checkprefix][func_name].func_name_separator if '[[' in args_and_sig: output_lines.append(check_label_format % (checkprefix, func_name, '', func_name_separator)) @@ -864,13 +901,19 @@ def add_checks(output_lines, comment_marker, prefix_list, func_dict, func_name, body_start = 0 else: output_lines.append('%s %s: %s' % (comment_marker, checkprefix, func_body[0])) - for func_line in func_body[body_start:]: + func_lines = generalize_asm_check_lines(func_body[body_start:], + vars_seen, global_vars_seen) + for func_line in func_lines: if func_line.strip() == '': output_lines.append('%s %s-EMPTY:' % (comment_marker, checkprefix)) else: check_suffix = '-NEXT' if not is_filtered else '' output_lines.append('%s %s%s: %s' % (comment_marker, checkprefix, check_suffix, func_line)) + # Remember new global variables we have not seen before + for key in global_vars_seen: + if key not in global_vars_seen_before: + global_vars_seen_dict[checkprefix][key] = global_vars_seen[key] break # For IR output, change all defs to FileCheck variables, so we're immune @@ -911,7 +954,7 @@ def add_checks(output_lines, comment_marker, prefix_list, func_dict, func_name, # line of code in the test function. output_lines.append(comment_marker) - # Remembe new global variables we have not seen before + # Remember new global variables we have not seen before for key in global_vars_seen: if key not in global_vars_seen_before: global_vars_seen_dict[checkprefix][key] = global_vars_seen[key] @@ -935,7 +978,7 @@ def add_analyze_checks(output_lines, comment_marker, prefix_list, func_dict, fun is_filtered) def build_global_values_dictionary(glob_val_dict, raw_tool_output, prefixes): - for nameless_value in nameless_values: + for nameless_value in itertools.chain(ir_nameless_values, asm_nameless_values): if nameless_value.global_ir_prefix is None: continue @@ -963,7 +1006,7 @@ def build_global_values_dictionary(glob_val_dict, raw_tool_output, prefixes): def add_global_checks(glob_val_dict, comment_marker, prefix_list, output_lines, global_vars_seen_dict, is_analyze, is_before_functions): printed_prefixes = set() - for nameless_value in nameless_values: + for nameless_value in ir_nameless_values: if nameless_value.global_ir_prefix is None: continue if nameless_value.is_before_functions != is_before_functions: |