blob: b59ca2529d622a276cc83545910d8eac733143bd [file] [log] [blame]
#!/usr/bin/python
#
# Copyright (C) 2023 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Generate LIR files out of the definition file.
* Operand usage
Register allocator needs operand usage to learn which operands can share the
same register.
To understand register sharing options, register allocator assumes insn works
in these steps:
- read input operands
- do the job
- write output operands
So, input-output operands should have dedicated registers, while input-only
operands can share registers with output-only operands.
There might be an exception when output-only operand is written before all
input-only operands are read, so its register can't be shared. Such operands
are usually referred as output-only-early-clobber operands.
For register sharing, output-only-early-clobber operand is the same as
input-output operand, but it is unnatural to describe output-only as
input-output, so we use a special keyword for it.
Finally, keywords are:
use - input-only
def - output-only
def_early_clobber - output-only-early-clobber
use_def - input-output
* Scratch operands
Scratch operands are actually output operands - indeed, their original value
is not used and they get some new value after the insn is done. However, they
are usually written before all input operands are read, so it makes sense to
describe scratch operands as output-only-early-clobber.
"""
import gen_lir_lib
import sys
def main(argv):
# Usage:
# gen_lir.py --headers <insn-inl.h>
# <machine_info-inl.h>
# <machine_opcode-inl.h>
# <machine_ir-inl.h>
# <lir_instructions.json>
# ...
# <machine_ir_intrinsic_binding.json>
# ...
# <def>
# ...
# gen_lir.py --sources <code_emit.cc>
# <code_debug.cc>
# <lir_instructions.json>
# ...
# <machine_ir_intrinsic_binding.json>
# ...
# <def>
# ...
mode = argv[1]
lir_def_files_begin = 6 if mode == '--headers' else 4
lir_def_files_end = lir_def_files_begin
while argv[lir_def_files_end].endswith('lir_instructions.json'):
lir_def_files_end += 1
arch_def_files_end = lir_def_files_end
while argv[arch_def_files_end].endswith('machine_ir_intrinsic_binding.json'):
arch_def_files_end += 1
if mode == '--headers':
arch, insns = gen_lir_lib.load_all_lir_defs(
argv[lir_def_files_begin:lir_def_files_end],
argv[lir_def_files_end:arch_def_files_end],
argv[arch_def_files_end:])
gen_lir_lib.gen_code_2_cc(argv[2], arch, insns)
gen_lir_lib.gen_machine_info_h(argv[3], arch, insns)
gen_lir_lib.gen_machine_opcode_h(argv[4], arch, insns)
gen_lir_lib.gen_machine_ir_h(argv[5], arch, insns)
elif mode == '--sources':
arch, insns = gen_lir_lib.load_all_lir_defs(
argv[lir_def_files_begin:lir_def_files_end],
argv[lir_def_files_end:arch_def_files_end],
argv[arch_def_files_end:])
gen_lir_lib.gen_code_emit_cc(argv[2], arch, insns)
gen_lir_lib.gen_code_debug_cc(argv[3], arch, insns)
else:
assert False, 'unknown option %s' % (mode)
return 0
if __name__ == '__main__':
sys.exit(main(sys.argv))