xref: /aosp_15_r20/art/tools/checker/checker.py (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker#!/usr/bin/env python3
2*795d594fSAndroid Build Coastguard Worker#
3*795d594fSAndroid Build Coastguard Worker# Copyright (C) 2014 The Android Open Source Project
4*795d594fSAndroid Build Coastguard Worker#
5*795d594fSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License");
6*795d594fSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License.
7*795d594fSAndroid Build Coastguard Worker# You may obtain a copy of the License at
8*795d594fSAndroid Build Coastguard Worker#
9*795d594fSAndroid Build Coastguard Worker#   http://www.apache.org/licenses/LICENSE-2.0
10*795d594fSAndroid Build Coastguard Worker#
11*795d594fSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software
12*795d594fSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS,
13*795d594fSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14*795d594fSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and
15*795d594fSAndroid Build Coastguard Worker# limitations under the License.
16*795d594fSAndroid Build Coastguard Worker
17*795d594fSAndroid Build Coastguard Workerimport argparse
18*795d594fSAndroid Build Coastguard Workerimport os
19*795d594fSAndroid Build Coastguard Worker
20*795d594fSAndroid Build Coastguard Workerfrom common.archs import archs_list
21*795d594fSAndroid Build Coastguard Workerfrom common.logger import Logger
22*795d594fSAndroid Build Coastguard Workerfrom file_format.c1visualizer.parser import parse_c1_visualizer_stream
23*795d594fSAndroid Build Coastguard Workerfrom file_format.checker.parser import parse_checker_stream
24*795d594fSAndroid Build Coastguard Workerfrom match.file import match_files
25*795d594fSAndroid Build Coastguard Worker
26*795d594fSAndroid Build Coastguard Worker
27*795d594fSAndroid Build Coastguard Workerdef parse_arguments():
28*795d594fSAndroid Build Coastguard Worker  parser = argparse.ArgumentParser()
29*795d594fSAndroid Build Coastguard Worker  parser.add_argument("tested_file",
30*795d594fSAndroid Build Coastguard Worker                      help="text file the checks should be verified against")
31*795d594fSAndroid Build Coastguard Worker  parser.add_argument("source_path", nargs="?",
32*795d594fSAndroid Build Coastguard Worker                      help="path to file/folder with checking annotations")
33*795d594fSAndroid Build Coastguard Worker  parser.add_argument("--check-prefix", dest="check_prefix", default="CHECK", metavar="PREFIX",
34*795d594fSAndroid Build Coastguard Worker                      help="prefix of checks in the test files (default: CHECK)")
35*795d594fSAndroid Build Coastguard Worker  parser.add_argument("--list-passes", dest="list_passes", action="store_true",
36*795d594fSAndroid Build Coastguard Worker                      help="print a list of all passes found in the tested file")
37*795d594fSAndroid Build Coastguard Worker  parser.add_argument("--dump-pass", dest="dump_pass", metavar="PASS",
38*795d594fSAndroid Build Coastguard Worker                      help="print a compiler pass dump")
39*795d594fSAndroid Build Coastguard Worker  parser.add_argument("--arch", dest="arch", choices=archs_list,
40*795d594fSAndroid Build Coastguard Worker                      help="Run tests for the specified target architecture.")
41*795d594fSAndroid Build Coastguard Worker  parser.add_argument("--debuggable", action="store_true",
42*795d594fSAndroid Build Coastguard Worker                      help="Run tests for debuggable code.")
43*795d594fSAndroid Build Coastguard Worker  parser.add_argument("--print-cfg", action="store_true", default="True", dest="print_cfg",
44*795d594fSAndroid Build Coastguard Worker                      help="Print the whole cfg file in case of test failure (default)")
45*795d594fSAndroid Build Coastguard Worker  parser.add_argument("--no-print-cfg", action="store_false", default="True", dest="print_cfg",
46*795d594fSAndroid Build Coastguard Worker                      help="Don't print the whole cfg file in case of test failure")
47*795d594fSAndroid Build Coastguard Worker  parser.add_argument("-q", "--quiet", action="store_true",
48*795d594fSAndroid Build Coastguard Worker                      help="print only errors")
49*795d594fSAndroid Build Coastguard Worker  return parser.parse_args()
50*795d594fSAndroid Build Coastguard Worker
51*795d594fSAndroid Build Coastguard Worker
52*795d594fSAndroid Build Coastguard Workerdef list_passes(output_filename):
53*795d594fSAndroid Build Coastguard Worker  c1_file = parse_c1_visualizer_stream(output_filename, open(output_filename, "r"))
54*795d594fSAndroid Build Coastguard Worker  for compiler_pass in c1_file.passes:
55*795d594fSAndroid Build Coastguard Worker    Logger.log(compiler_pass.name)
56*795d594fSAndroid Build Coastguard Worker
57*795d594fSAndroid Build Coastguard Worker
58*795d594fSAndroid Build Coastguard Workerdef dump_pass(output_filename, pass_name):
59*795d594fSAndroid Build Coastguard Worker  c1_file = parse_c1_visualizer_stream(output_filename, open(output_filename, "r"))
60*795d594fSAndroid Build Coastguard Worker  compiler_pass = c1_file.find_pass(pass_name)
61*795d594fSAndroid Build Coastguard Worker  if compiler_pass:
62*795d594fSAndroid Build Coastguard Worker    max_line_no = compiler_pass.start_line_no + len(compiler_pass.body)
63*795d594fSAndroid Build Coastguard Worker    len_line_no = len(str(max_line_no)) + 2
64*795d594fSAndroid Build Coastguard Worker    cur_line_no = compiler_pass.start_line_no
65*795d594fSAndroid Build Coastguard Worker    for line in compiler_pass.body:
66*795d594fSAndroid Build Coastguard Worker      Logger.log((str(cur_line_no) + ":").ljust(len_line_no) + line)
67*795d594fSAndroid Build Coastguard Worker      cur_line_no += 1
68*795d594fSAndroid Build Coastguard Worker  else:
69*795d594fSAndroid Build Coastguard Worker    Logger.fail('Pass "{}" not found in the output'.format(pass_name))
70*795d594fSAndroid Build Coastguard Worker
71*795d594fSAndroid Build Coastguard Worker
72*795d594fSAndroid Build Coastguard Workerdef find_checker_files(path):
73*795d594fSAndroid Build Coastguard Worker  """ Returns a list of files to scan for check annotations in the given path.
74*795d594fSAndroid Build Coastguard Worker      Path to a file is returned as a single-element list, directories are
75*795d594fSAndroid Build Coastguard Worker      recursively traversed and all '.java', '.j', and '.smali' files returned.
76*795d594fSAndroid Build Coastguard Worker  """
77*795d594fSAndroid Build Coastguard Worker  if not path:
78*795d594fSAndroid Build Coastguard Worker    Logger.fail("No source path provided")
79*795d594fSAndroid Build Coastguard Worker  elif os.path.isfile(path):
80*795d594fSAndroid Build Coastguard Worker    return [path]
81*795d594fSAndroid Build Coastguard Worker  elif os.path.isdir(path):
82*795d594fSAndroid Build Coastguard Worker    found_files = []
83*795d594fSAndroid Build Coastguard Worker    for root, dirs, files in os.walk(path):
84*795d594fSAndroid Build Coastguard Worker      for file in files:
85*795d594fSAndroid Build Coastguard Worker        extension = os.path.splitext(file)[1]
86*795d594fSAndroid Build Coastguard Worker        if extension in [".java", ".smali", ".j"]:
87*795d594fSAndroid Build Coastguard Worker          found_files.append(os.path.join(root, file))
88*795d594fSAndroid Build Coastguard Worker    return found_files
89*795d594fSAndroid Build Coastguard Worker  else:
90*795d594fSAndroid Build Coastguard Worker    Logger.fail('Source path "{}" not found'.format(path))
91*795d594fSAndroid Build Coastguard Worker
92*795d594fSAndroid Build Coastguard Worker
93*795d594fSAndroid Build Coastguard Workerdef run_tests(check_prefix, check_path, output_filename, target_arch, debuggable_mode, print_cfg):
94*795d594fSAndroid Build Coastguard Worker  c1_file = parse_c1_visualizer_stream(output_filename, open(output_filename, "r"))
95*795d594fSAndroid Build Coastguard Worker  for check_filename in find_checker_files(check_path):
96*795d594fSAndroid Build Coastguard Worker    checker_file = parse_checker_stream(os.path.basename(check_filename),
97*795d594fSAndroid Build Coastguard Worker                                        check_prefix,
98*795d594fSAndroid Build Coastguard Worker                                        open(check_filename, "r"),
99*795d594fSAndroid Build Coastguard Worker                                        target_arch)
100*795d594fSAndroid Build Coastguard Worker    match_files(checker_file, c1_file, target_arch, debuggable_mode, print_cfg)
101*795d594fSAndroid Build Coastguard Worker
102*795d594fSAndroid Build Coastguard Worker
103*795d594fSAndroid Build Coastguard Workerif __name__ == "__main__":
104*795d594fSAndroid Build Coastguard Worker  args = parse_arguments()
105*795d594fSAndroid Build Coastguard Worker
106*795d594fSAndroid Build Coastguard Worker  if args.quiet:
107*795d594fSAndroid Build Coastguard Worker    Logger.Verbosity = Logger.Level.ERROR
108*795d594fSAndroid Build Coastguard Worker
109*795d594fSAndroid Build Coastguard Worker  if args.list_passes:
110*795d594fSAndroid Build Coastguard Worker    list_passes(args.tested_file)
111*795d594fSAndroid Build Coastguard Worker  elif args.dump_pass:
112*795d594fSAndroid Build Coastguard Worker    dump_pass(args.tested_file, args.dump_pass)
113*795d594fSAndroid Build Coastguard Worker  else:
114*795d594fSAndroid Build Coastguard Worker    run_tests(args.check_prefix, args.source_path, args.tested_file, args.arch, args.debuggable,
115*795d594fSAndroid Build Coastguard Worker              args.print_cfg)
116