mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-11-27 23:51:56 +00:00
[utils] remove ability to generate llc check lines from update_test_checks.py
The dream of a unified check-line auto-generator for all phases of compilation is dead. The llc script has already diverged to be better at its goal, so having 2 scripts that do almost the same thing just causes confusion. Now, this script will only work with opt to produce check lines for IR transforms. llvm-svn: 305208
This commit is contained in:
parent
b5fe855dfb
commit
cae64a0497
@ -1,13 +1,13 @@
|
||||
#!/usr/bin/env python2.7
|
||||
|
||||
"""A script to generate FileCheck statements for regression tests.
|
||||
"""A script to generate FileCheck statements for 'opt' regression tests.
|
||||
|
||||
This script is a utility to update LLVM opt or llc test cases with new
|
||||
This script is a utility to update LLVM opt test cases with new
|
||||
FileCheck patterns. It can either update all of the tests in the file or
|
||||
a single test function.
|
||||
|
||||
Example usage:
|
||||
$ update_test_checks.py --tool=../bin/opt test/foo.ll
|
||||
$ update_test_checks.py --opt=../bin/opt test/foo.ll
|
||||
|
||||
Workflow:
|
||||
1. Make a compiler patch that requires updating some number of FileCheck lines
|
||||
@ -45,23 +45,11 @@ ADVERT = '; NOTE: Assertions have been autogenerated by '
|
||||
SCRUB_LEADING_WHITESPACE_RE = re.compile(r'^(\s+)')
|
||||
SCRUB_WHITESPACE_RE = re.compile(r'(?!^(| \w))[ \t]+', flags=re.M)
|
||||
SCRUB_TRAILING_WHITESPACE_RE = re.compile(r'[ \t]+$', flags=re.M)
|
||||
SCRUB_X86_SHUFFLES_RE = (
|
||||
re.compile(
|
||||
r'^(\s*\w+) [^#\n]+#+ ((?:[xyz]mm\d+|mem)( \{%k\d+\}( \{z\})?)? = .*)$',
|
||||
flags=re.M))
|
||||
SCRUB_X86_SP_RE = re.compile(r'\d+\(%(esp|rsp)\)')
|
||||
SCRUB_X86_RIP_RE = re.compile(r'[.\w]+\(%rip\)')
|
||||
SCRUB_X86_LCP_RE = re.compile(r'\.LCPI[0-9]+_[0-9]+')
|
||||
SCRUB_KILL_COMMENT_RE = re.compile(r'^ *#+ +kill:.*\n')
|
||||
SCRUB_IR_COMMENT_RE = re.compile(r'\s*;.*')
|
||||
|
||||
RUN_LINE_RE = re.compile('^\s*;\s*RUN:\s*(.*)$')
|
||||
IR_FUNCTION_RE = re.compile('^\s*define\s+(?:internal\s+)?[^@]*@([\w-]+)\s*\(')
|
||||
LLC_FUNCTION_RE = re.compile(
|
||||
r'^_?(?P<func>[^:]+):[ \t]*#+[ \t]*@(?P=func)\n[^:]*?'
|
||||
r'(?P<body>^##?[ \t]+[^:]+:.*?)\s*'
|
||||
r'^\s*(?:[^:\n]+?:\s*\n\s*\.size|\.cfi_endproc|\.globl|\.comm|\.(?:sub)?section)',
|
||||
flags=(re.M | re.S))
|
||||
OPT_FUNCTION_RE = re.compile(
|
||||
r'^\s*define\s+(?:internal\s+)?[^@]*@(?P<func>[\w-]+?)\s*\('
|
||||
r'(\s+)?[^)]*[^{]*\{\n(?P<body>.*?)^\}$',
|
||||
@ -76,29 +64,14 @@ IR_VALUE_RE = re.compile(r'(\s+)%([\w\.]+?)([,\s\(\)]|\Z)')
|
||||
# Invoke the tool that is being tested.
|
||||
def invoke_tool(args, cmd_args, ir):
|
||||
with open(ir) as ir_file:
|
||||
stdout = subprocess.check_output(args.tool_binary + ' ' + cmd_args,
|
||||
stdout = subprocess.check_output(args.opt_binary + ' ' + cmd_args,
|
||||
shell=True, stdin=ir_file)
|
||||
# Fix line endings to unix CR style.
|
||||
stdout = stdout.replace('\r\n', '\n')
|
||||
return stdout
|
||||
|
||||
|
||||
# FIXME: Separate the x86-specific scrubbers, so this can be used for other targets.
|
||||
def scrub_asm(asm):
|
||||
# Detect shuffle asm comments and hide the operands in favor of the comments.
|
||||
asm = SCRUB_X86_SHUFFLES_RE.sub(r'\1 {{.*#+}} \2', asm)
|
||||
# Generically match the stack offset of a memory operand.
|
||||
asm = SCRUB_X86_SP_RE.sub(r'{{[0-9]+}}(%\1)', asm)
|
||||
# Generically match a RIP-relative memory operand.
|
||||
asm = SCRUB_X86_RIP_RE.sub(r'{{.*}}(%rip)', asm)
|
||||
# Generically match a LCP symbol.
|
||||
asm = SCRUB_X86_LCP_RE.sub(r'{{\.LCPI.*}}', asm)
|
||||
# Strip kill operands inserted into the asm.
|
||||
asm = SCRUB_KILL_COMMENT_RE.sub('', asm)
|
||||
return asm
|
||||
|
||||
|
||||
def scrub_body(body, tool_basename):
|
||||
def scrub_body(body, opt_basename):
|
||||
# Scrub runs of whitespace out of the assembly, but leave the leading
|
||||
# whitespace in place.
|
||||
body = SCRUB_WHITESPACE_RE.sub(r' ', body)
|
||||
@ -106,22 +79,17 @@ def scrub_body(body, tool_basename):
|
||||
body = string.expandtabs(body, 2)
|
||||
# Strip trailing whitespace.
|
||||
body = SCRUB_TRAILING_WHITESPACE_RE.sub(r'', body)
|
||||
if tool_basename == "llc":
|
||||
body = scrub_asm(body)
|
||||
return body
|
||||
|
||||
|
||||
# Build up a dictionary of all the function bodies.
|
||||
def build_function_body_dictionary(raw_tool_output, prefixes, func_dict, verbose, tool_basename):
|
||||
if tool_basename == "llc":
|
||||
func_regex = LLC_FUNCTION_RE
|
||||
else:
|
||||
func_regex = OPT_FUNCTION_RE
|
||||
def build_function_body_dictionary(raw_tool_output, prefixes, func_dict, verbose, opt_basename):
|
||||
func_regex = OPT_FUNCTION_RE
|
||||
for m in func_regex.finditer(raw_tool_output):
|
||||
if not m:
|
||||
continue
|
||||
func = m.group('func')
|
||||
scrubbed_body = scrub_body(m.group('body'), tool_basename)
|
||||
scrubbed_body = scrub_body(m.group('body'), opt_basename)
|
||||
if func.startswith('stress'):
|
||||
# We only use the last line of the function body for stress tests.
|
||||
scrubbed_body = '\n'.join(scrubbed_body.splitlines()[-1:])
|
||||
@ -188,12 +156,9 @@ def genericize_check_lines(lines):
|
||||
return lines
|
||||
|
||||
|
||||
def add_checks(output_lines, prefix_list, func_dict, func_name, tool_basename):
|
||||
# Select a label format based on the whether we're checking asm or IR.
|
||||
if tool_basename == "llc":
|
||||
check_label_format = "; %s-LABEL: %s:"
|
||||
else:
|
||||
check_label_format = "; %s-LABEL: @%s("
|
||||
def add_checks(output_lines, prefix_list, func_dict, func_name, opt_basename):
|
||||
# Label format is based on IR string.
|
||||
check_label_format = "; %s-LABEL: @%s("
|
||||
|
||||
printed_prefixes = []
|
||||
for checkprefixes, _ in prefix_list:
|
||||
@ -212,8 +177,7 @@ def add_checks(output_lines, prefix_list, func_dict, func_name, tool_basename):
|
||||
|
||||
# For IR output, change all defs to FileCheck variables, so we're immune
|
||||
# to variable naming fashions.
|
||||
if tool_basename == "opt":
|
||||
func_body = genericize_check_lines(func_body)
|
||||
func_body = genericize_check_lines(func_body)
|
||||
|
||||
# This could be selectively enabled with an optional invocation argument.
|
||||
# Disabled for now: better to check everything. Be safe rather than sorry.
|
||||
@ -226,20 +190,14 @@ def add_checks(output_lines, prefix_list, func_dict, func_name, tool_basename):
|
||||
# output_lines.append('; %s: %s' % (checkprefix, func_body[0]))
|
||||
# is_blank_line = False
|
||||
|
||||
# For llc tests, there may be asm directives between the label and the
|
||||
# first checked line (most likely that first checked line is "# BB#0").
|
||||
if tool_basename == "opt":
|
||||
is_blank_line = False
|
||||
else:
|
||||
is_blank_line = True;
|
||||
is_blank_line = False
|
||||
|
||||
for func_line in func_body:
|
||||
if func_line.strip() == '':
|
||||
is_blank_line = True
|
||||
continue
|
||||
# Do not waste time checking IR comments.
|
||||
if tool_basename == "opt":
|
||||
func_line = SCRUB_IR_COMMENT_RE.sub(r'', func_line)
|
||||
func_line = SCRUB_IR_COMMENT_RE.sub(r'', func_line)
|
||||
|
||||
# Skip blank lines instead of checking them.
|
||||
if is_blank_line == True:
|
||||
@ -275,8 +233,8 @@ def main():
|
||||
parser = argparse.ArgumentParser(description=__doc__, formatter_class=RawTextHelpFormatter)
|
||||
parser.add_argument('-v', '--verbose', action='store_true',
|
||||
help='Show verbose output')
|
||||
parser.add_argument('--tool-binary', default='llc',
|
||||
help='The tool used to generate the test case')
|
||||
parser.add_argument('--opt-binary', default='opt',
|
||||
help='The opt binary used to generate the test case')
|
||||
parser.add_argument(
|
||||
'--function', help='The function in the test file to update')
|
||||
parser.add_argument('tests', nargs='+')
|
||||
@ -284,9 +242,9 @@ def main():
|
||||
|
||||
autogenerated_note = (ADVERT + 'utils/' + os.path.basename(__file__))
|
||||
|
||||
tool_basename = os.path.basename(args.tool_binary)
|
||||
if (tool_basename != "llc" and tool_basename != "opt"):
|
||||
print >>sys.stderr, 'ERROR: Unexpected tool name: ' + tool_basename
|
||||
opt_basename = os.path.basename(args.opt_binary)
|
||||
if (opt_basename != "opt"):
|
||||
print >>sys.stderr, 'ERROR: Unexpected opt name: ' + opt_basename
|
||||
sys.exit(1)
|
||||
|
||||
for test in args.tests:
|
||||
@ -313,15 +271,15 @@ def main():
|
||||
for l in run_lines:
|
||||
(tool_cmd, filecheck_cmd) = tuple([cmd.strip() for cmd in l.split('|', 1)])
|
||||
|
||||
if not tool_cmd.startswith(tool_basename + ' '):
|
||||
print >>sys.stderr, 'WARNING: Skipping non-%s RUN line: %s' % (tool_basename, l)
|
||||
if not tool_cmd.startswith(opt_basename + ' '):
|
||||
print >>sys.stderr, 'WARNING: Skipping non-%s RUN line: %s' % (opt_basename, l)
|
||||
continue
|
||||
|
||||
if not filecheck_cmd.startswith('FileCheck '):
|
||||
print >>sys.stderr, 'WARNING: Skipping non-FileChecked RUN line: ' + l
|
||||
continue
|
||||
|
||||
tool_cmd_args = tool_cmd[len(tool_basename):].strip()
|
||||
tool_cmd_args = tool_cmd[len(opt_basename):].strip()
|
||||
tool_cmd_args = tool_cmd_args.replace('< %s', '').replace('%s', '').strip()
|
||||
|
||||
check_prefixes = [item for m in CHECK_PREFIX_RE.finditer(filecheck_cmd)
|
||||
@ -337,13 +295,13 @@ def main():
|
||||
for prefixes, _ in prefix_list:
|
||||
for prefix in prefixes:
|
||||
func_dict.update({prefix: dict()})
|
||||
for prefixes, tool_args in prefix_list:
|
||||
for prefixes, opt_args in prefix_list:
|
||||
if args.verbose:
|
||||
print >>sys.stderr, 'Extracted tool cmd: ' + tool_basename + ' ' + tool_args
|
||||
print >>sys.stderr, 'Extracted opt cmd: ' + opt_basename + ' ' + opt_args
|
||||
print >>sys.stderr, 'Extracted FileCheck prefixes: ' + str(prefixes)
|
||||
|
||||
raw_tool_output = invoke_tool(args, tool_args, test)
|
||||
build_function_body_dictionary(raw_tool_output, prefixes, func_dict, args.verbose, tool_basename)
|
||||
raw_tool_output = invoke_tool(args, opt_args, test)
|
||||
build_function_body_dictionary(raw_tool_output, prefixes, func_dict, args.verbose, opt_basename)
|
||||
|
||||
is_in_function = False
|
||||
is_in_function_start = False
|
||||
@ -364,7 +322,7 @@ def main():
|
||||
continue
|
||||
|
||||
# Print out the various check lines here.
|
||||
output_lines = add_checks(output_lines, prefix_list, func_dict, name, tool_basename)
|
||||
output_lines = add_checks(output_lines, prefix_list, func_dict, name, opt_basename)
|
||||
is_in_function_start = False
|
||||
|
||||
if is_in_function:
|
||||
|
Loading…
Reference in New Issue
Block a user