xref: /aosp_15_r20/external/XNNPACK/tools/check-assembly-and-jit-microkernels-in-sync.py (revision 4bdc94577ba0e567308109d787f7fec7b531ce36)
1*4bdc9457SAndroid Build Coastguard Worker#!/usr/bin/env python
2*4bdc9457SAndroid Build Coastguard Worker# Copyright 2022 Google LLC
3*4bdc9457SAndroid Build Coastguard Worker#
4*4bdc9457SAndroid Build Coastguard Worker# This source code is licensed under the BSD-style license found in the
5*4bdc9457SAndroid Build Coastguard Worker# LICENSE file in the root directory of this source tree.
6*4bdc9457SAndroid Build Coastguard Worker
7*4bdc9457SAndroid Build Coastguard Workerfrom pathlib import Path
8*4bdc9457SAndroid Build Coastguard Workerimport subprocess
9*4bdc9457SAndroid Build Coastguard Worker
10*4bdc9457SAndroid Build Coastguard Worker
11*4bdc9457SAndroid Build Coastguard Worker# Check if `line` can be found in file.
12*4bdc9457SAndroid Build Coastguard Workerdef line_in_file(line, filename):
13*4bdc9457SAndroid Build Coastguard Worker  with open(filename) as o:
14*4bdc9457SAndroid Build Coastguard Worker    return any(line in l for l in o)
15*4bdc9457SAndroid Build Coastguard Worker
16*4bdc9457SAndroid Build Coastguard Worker
17*4bdc9457SAndroid Build Coastguard Worker# Finds all the JIT generated microkernel cc files.
18*4bdc9457SAndroid Build Coastguard Worker# We could use the JIT_AARCH32_SRCS and JIT_AARCH64_SRCS in BUILD too.
19*4bdc9457SAndroid Build Coastguard Workerdef find_jit_files():
20*4bdc9457SAndroid Build Coastguard Worker  paths = list(Path('src').glob('**/*.cc'))
21*4bdc9457SAndroid Build Coastguard Worker  return [p for p in paths if line_in_file('Converted from', p)]
22*4bdc9457SAndroid Build Coastguard Worker
23*4bdc9457SAndroid Build Coastguard Worker
24*4bdc9457SAndroid Build Coastguard Worker# Check that file exists.
25*4bdc9457SAndroid Build Coastguard Workerdef check_assembly_file_exists(filename):
26*4bdc9457SAndroid Build Coastguard Worker  p = Path('.')
27*4bdc9457SAndroid Build Coastguard Worker  assert((p / filename).exists())
28*4bdc9457SAndroid Build Coastguard Worker
29*4bdc9457SAndroid Build Coastguard Worker
30*4bdc9457SAndroid Build Coastguard Worker# JIT microkernel can be converted from a assembly file or a templated assembly file, gets the right "root" file.
31*4bdc9457SAndroid Build Coastguard Workerdef get_assembly_file_or_template(converted_from):
32*4bdc9457SAndroid Build Coastguard Worker  file = converted_from
33*4bdc9457SAndroid Build Coastguard Worker  with open(converted_from) as f:
34*4bdc9457SAndroid Build Coastguard Worker    for line in f.readlines():
35*4bdc9457SAndroid Build Coastguard Worker      if 'Template: ' in line:
36*4bdc9457SAndroid Build Coastguard Worker        file = line.split()[2]
37*4bdc9457SAndroid Build Coastguard Worker        break
38*4bdc9457SAndroid Build Coastguard Worker  if file.startswith('/'):
39*4bdc9457SAndroid Build Coastguard Worker    file = file[len('/'):]
40*4bdc9457SAndroid Build Coastguard Worker  return file
41*4bdc9457SAndroid Build Coastguard Worker
42*4bdc9457SAndroid Build Coastguard Worker
43*4bdc9457SAndroid Build Coastguard Worker# Finds the assembly file associated with the JIT file to write the LINT marker to.
44*4bdc9457SAndroid Build Coastguard Workerdef find_assembly_file(jit_file):
45*4bdc9457SAndroid Build Coastguard Worker  with jit_file.open() as f:
46*4bdc9457SAndroid Build Coastguard Worker    for line in f.readlines():
47*4bdc9457SAndroid Build Coastguard Worker      if 'Converted from' in line:
48*4bdc9457SAndroid Build Coastguard Worker        converted_from = line.split()[3]
49*4bdc9457SAndroid Build Coastguard Worker        check_assembly_file_exists(converted_from)
50*4bdc9457SAndroid Build Coastguard Worker        assembly_file = get_assembly_file_or_template(converted_from)
51*4bdc9457SAndroid Build Coastguard Worker        return assembly_file
52*4bdc9457SAndroid Build Coastguard Worker    return f'{jit_file} does not have converted from'
53*4bdc9457SAndroid Build Coastguard Worker
54*4bdc9457SAndroid Build Coastguard Worker
55*4bdc9457SAndroid Build Coastguard Worker# Writes LINT markers to `assembly_file`.
56*4bdc9457SAndroid Build Coastguard Workerdef write_lint_markers(assembly_file, jit_file):
57*4bdc9457SAndroid Build Coastguard Worker  with open(assembly_file) as f:
58*4bdc9457SAndroid Build Coastguard Worker    lines = f.readlines()
59*4bdc9457SAndroid Build Coastguard Worker    if any('LINT.IfChange' in l for l in lines):
60*4bdc9457SAndroid Build Coastguard Worker      # Has lint marker, check that the JIT file is found.
61*4bdc9457SAndroid Build Coastguard Worker      if not any(jit_file.name in l for l in lines):
62*4bdc9457SAndroid Build Coastguard Worker        print(f'{jit_file.name} not found in {assembly_file}')
63*4bdc9457SAndroid Build Coastguard Worker        assert(False)
64*4bdc9457SAndroid Build Coastguard Worker      return
65*4bdc9457SAndroid Build Coastguard Worker
66*4bdc9457SAndroid Build Coastguard Worker  relative_jit_file = jit_file.name
67*4bdc9457SAndroid Build Coastguard Worker  # This sed script will write LINT markers that wraps the function definition in the assembly file.
68*4bdc9457SAndroid Build Coastguard Worker  sed_args = [
69*4bdc9457SAndroid Build Coastguard Worker      'sed',
70*4bdc9457SAndroid Build Coastguard Worker      '-i',
71*4bdc9457SAndroid Build Coastguard Worker      '-e',
72*4bdc9457SAndroid Build Coastguard Worker      '/# void xnn/i# LINT.IfChange',
73*4bdc9457SAndroid Build Coastguard Worker      '-e',
74*4bdc9457SAndroid Build Coastguard Worker      '/\/\/ void xnn/i# LINT.IfChange',
75*4bdc9457SAndroid Build Coastguard Worker      '-e',
76*4bdc9457SAndroid Build Coastguard Worker      f'/END_FUNCTION/a# LINT.ThenChange({relative_jit_file})',
77*4bdc9457SAndroid Build Coastguard Worker      assembly_file,
78*4bdc9457SAndroid Build Coastguard Worker  ]
79*4bdc9457SAndroid Build Coastguard Worker  subprocess.run(sed_args)
80*4bdc9457SAndroid Build Coastguard Worker
81*4bdc9457SAndroid Build Coastguard Worker
82*4bdc9457SAndroid Build Coastguard Workerdef main():
83*4bdc9457SAndroid Build Coastguard Worker  for f in find_jit_files():
84*4bdc9457SAndroid Build Coastguard Worker    write_lint_markers(find_assembly_file(f), f)
85*4bdc9457SAndroid Build Coastguard Worker
86*4bdc9457SAndroid Build Coastguard Worker
87*4bdc9457SAndroid Build Coastguard Workerif __name__ == '__main__':
88*4bdc9457SAndroid Build Coastguard Worker  main()
89