brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.0 KiB · ba70249 Raw
197 lines · python
1#!/usr/bin/env python32 3"""Updates FileCheck checks in MIR tests.4 5This script is a utility to update MIR based tests with new FileCheck6patterns.7 8The checks added by this script will cover the entire body of each9function it handles. Virtual registers used are given names via10FileCheck patterns, so if you do want to check a subset of the body it11should be straightforward to trim out the irrelevant parts. None of12the YAML metadata will be checked, other than function names, and fixedStack13if the --print-fixed-stack option is used.14 15If there are multiple llc commands in a test, the full set of checks16will be repeated for each different check pattern. Checks for patterns17that are common between different commands will be left as-is by18default, or removed if the --remove-common-prefixes flag is provided.19"""20 21from __future__ import print_function22 23from sys import stderr24from traceback import print_exc25import argparse26import collections27import glob28import os29import re30import subprocess31import sys32 33from UpdateTestChecks import common34from UpdateTestChecks import mir35 36 37class LLC:38    def __init__(self, bin):39        self.bin = bin40 41    def __call__(self, args, ir):42        if ir.endswith(".mir"):43            args = "{} -x mir".format(args)44        with open(ir) as ir_file:45            stdout = subprocess.check_output(46                "{} {}".format(self.bin, args), shell=True, stdin=ir_file47            )48            if sys.version_info[0] > 2:49                stdout = stdout.decode()50            # Fix line endings to unix CR style.51            stdout = stdout.replace("\r\n", "\n")52        return stdout53 54 55def log(msg, verbose=True):56    if verbose:57        print(msg, file=sys.stderr)58 59 60def find_triple_in_ir(lines, verbose=False):61    for l in lines:62        m = common.TRIPLE_IR_RE.match(l)63        if m:64            return m.group(1)65    return None66 67 68def build_run_list(test, run_lines, verbose=False):69    run_list = []70    all_prefixes = []71    for l in run_lines:72        if "|" not in l:73            common.warn("Skipping unparsable RUN line: " + l)74            continue75 76        commands = [cmd.strip() for cmd in l.split("|", 1)]77        llc_cmd = commands[0]78        filecheck_cmd = commands[1] if len(commands) > 1 else ""79        common.verify_filecheck_prefixes(filecheck_cmd)80 81        if not llc_cmd.startswith("llc "):82            common.warn("Skipping non-llc RUN line: {}".format(l), test_file=test)83            continue84        if not filecheck_cmd.startswith("FileCheck "):85            common.warn(86                "Skipping non-FileChecked RUN line: {}".format(l), test_file=test87            )88            continue89 90        triple = None91        m = common.TRIPLE_ARG_RE.search(llc_cmd)92        if m:93            triple = m.group(1)94        # If we find -march but not -mtriple, use that.95        m = common.MARCH_ARG_RE.search(llc_cmd)96        if m and not triple:97            triple = "{}--".format(m.group(1))98 99        cmd_args = llc_cmd[len("llc") :].strip()100        cmd_args = cmd_args.replace("< %s", "").replace("%s", "").strip()101        check_prefixes = common.get_check_prefixes(filecheck_cmd)102        all_prefixes += check_prefixes103 104        run_list.append((check_prefixes, cmd_args, triple))105 106    # Sort prefixes that are shared between run lines before unshared prefixes.107    # This causes us to prefer printing shared prefixes.108    for run in run_list:109        run[0].sort(key=lambda prefix: -all_prefixes.count(prefix))110 111    return run_list112 113 114def update_test_file(args, test, autogenerated_note):115    with open(test) as fd:116        input_lines = [l.rstrip() for l in fd]117 118    triple_in_ir = find_triple_in_ir(input_lines, args.verbose)119    run_lines = common.find_run_lines(test, input_lines)120    run_list = build_run_list(test, run_lines, args.verbose)121 122    func_dict = {}123    for run in run_list:124        for prefix in run[0]:125            func_dict.update({prefix: dict()})126    for prefixes, llc_args, triple_in_cmd in run_list:127        log("Extracted LLC cmd: llc {}".format(llc_args), args.verbose)128        log("Extracted FileCheck prefixes: {}".format(prefixes), args.verbose)129 130        raw_tool_output = args.llc_binary(llc_args, test)131        if not triple_in_cmd and not triple_in_ir:132            common.warn("No triple found: skipping file", test_file=test)133            return134 135        mir.build_function_info_dictionary(136            test,137            raw_tool_output,138            triple_in_cmd or triple_in_ir,139            prefixes,140            func_dict,141            args.verbose,142        )143 144    prefix_set = set([prefix for run in run_list for prefix in run[0]])145    log("Rewriting FileCheck prefixes: {}".format(prefix_set), args.verbose)146 147    output_lines = mir.add_mir_checks(148        input_lines,149        prefix_set,150        autogenerated_note,151        test,152        run_list,153        func_dict,154        args.print_fixed_stack,155        first_check_is_next=False,156        at_the_function_name=False,157    )158 159    log("Writing {} lines to {}...".format(len(output_lines), test), args.verbose)160 161    with open(test, "wb") as fd:162        fd.writelines(["{}\n".format(l).encode("utf-8") for l in output_lines])163 164 165def main():166    parser = argparse.ArgumentParser(167        description=__doc__, formatter_class=argparse.RawTextHelpFormatter168    )169    parser.add_argument(170        "--llc-binary",171        default="llc",172        type=LLC,173        help='The "llc" binary to generate the test case with',174    )175    parser.add_argument(176        "--print-fixed-stack",177        action="store_true",178        help="Add check lines for fixedStack",179    )180    parser.add_argument("tests", nargs="+")181    args = common.parse_commandline_args(parser)182 183    script_name = os.path.basename(__file__)184    returncode = 0185    for ti in common.itertests(args.tests, parser, script_name="utils/" + script_name):186        try:187            update_test_file(ti.args, ti.path, ti.test_autogenerated_note)188        except Exception as e:189            stderr.write(f"Error: Failed to update test {ti.path}\n")190            print_exc()191            returncode = 1192    return returncode193 194 195if __name__ == "__main__":196    sys.exit(main())197