Add scripts/gen-target-info.py to generate declarations and definitions for exact-target and base-family architecture checks from system target names and their TARGET_BASE_ARCH values.
Provide target_is_<arch>() and target_is_base_<family>() checks for an explicit TargetInfo. Retain target_<arch>() and target_base_<family>() as wrappers using the current target. Wire the generator into Meson using all system target definitions so the available checks do not depend on --target-list. Signed-off-by: Yonggang Luo <[email protected]> --- include/qemu/target-info.h | 76 ++++------------------------- meson.build | 16 ++++++ scripts/gen-target-info.py | 99 ++++++++++++++++++++++++++++++++++++++ target-info.c | 62 +----------------------- 4 files changed, 125 insertions(+), 128 deletions(-) create mode 100644 scripts/gen-target-info.py diff --git a/include/qemu/target-info.h b/include/qemu/target-info.h index d1928cecf84..88aa80e918c 100644 --- a/include/qemu/target-info.h +++ b/include/qemu/target-info.h @@ -51,74 +51,16 @@ const char *target_cpu_type(void); */ bool target_big_endian(void); -/** - * target_base_arm: - * - * Returns whether the target architecture is ARM or Aarch64. - */ -bool target_base_arm(void); - -/** - * target_arm: - * - * Returns whether the target architecture is ARM (32-bit, not Aarch64). - */ -bool target_arm(void); - -/** - * target_aarch64: - * - * Returns whether the target architecture is Aarch64. - */ -bool target_aarch64(void); - -/** - * target_m68k: - * - * Returns whether the target architecture is M68K. - */ -bool target_m68k(void); - -/** - * target_or1k: - * - * Returns whether the target architecture is OpenRISC 1000. - */ -bool target_or1k(void); - -/** - * target_base_ppc: - * - * Returns whether the target architecture is PowerPC 32-bit or 64-bit. - */ -bool target_base_ppc(void); - -/** - * target_ppc: - * - * Returns whether the target architecture is PowerPC 32-bit. - */ -bool target_ppc(void); - -/** - * target_ppc64: - * - * Returns whether the target architecture is PowerPC 64-bit. - */ -bool target_ppc64(void); - -/** - * target_s390x: - * - * Returns whether the target architecture is S390x. - */ -bool target_s390x(void); - -/** - * target_riscv64: +/* + * Exact-target and base-family helpers, generated by + * scripts/gen-target-info.py from the TARGET_BASE_ARCH of every + * system target: * - * Returns whether the target architecture is riscv64 + * bool target_is_<arch>(const TargetInfo *ti); + * bool target_<arch>(void); + * bool target_is_base_<family>(const TargetInfo *ti); + * bool target_base_<family>(void); */ -bool target_riscv64(void); +#include "target-info-gen.h" #endif diff --git a/meson.build b/meson.build index d070dafe2a9..8799b3f6d51 100644 --- a/meson.build +++ b/meson.build @@ -3581,6 +3581,22 @@ foreach d : hx_headers endforeach genh += hxdep +# Use target_mak_all, not target_dirs, so the generated helpers do not +# depend on --target-list. +target_info_gen_args = [] +foreach target, mak : target_mak_all + if target.endswith('-softmmu') + target_info_gen_args += ['--target', + target.split('-')[0] + '=' + mak['TARGET_BASE_ARCH']] + endif +endforeach +target_info_gen = custom_target('target-info-gen', + output: ['target-info-gen.h', 'target-info-gen.c.inc'], + depend_files: files('scripts/qapi/common.py'), + command: [python, files('scripts/gen-target-info.py'), + target_info_gen_args, '@OUTDIR@']) +genh += target_info_gen + ############### # Trace files # ############### diff --git a/scripts/gen-target-info.py b/scripts/gen-target-info.py new file mode 100644 index 00000000000..a4c3474140f --- /dev/null +++ b/scripts/gen-target-info.py @@ -0,0 +1,99 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: GPL-2.0-or-later +"""Generate TargetInfo target helpers and abstract machine parents. + +meson passes every system target with its TARGET_BASE_ARCH, independent +of --target-list, as --target <name>=<base>. <name> is a SysEmuTarget +member; a target without one fails to compile. + +For every target <arch> and every base family <family>: + bool target_is_<arch>(const TargetInfo *ti); + bool target_<arch>(void); + bool target_is_base_<family>(const TargetInfo *ti); + bool target_base_<family>(void); + TYPE_TARGET_<ARCH>_MACHINE "target-<arch>-machine" + TYPE_TARGET_BASE_<FAMILY>_MACHINE "target-base-<family>-machine" + +Machine parents are abstract and only registered when available. +<arch> parents inherit their <family> parent, which inherits TYPE_MACHINE. +""" + +import argparse +import os +import re +import sys +from typing import Dict, List + +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) +from qapi.common import c_enum_const, c_name + +HEADER = "/* Generated by scripts/gen-target-info.py. Do not edit. */" +C_IDENT = re.compile(r"^[A-Za-z_][A-Za-z0-9_]*$") + + +def parse_targets(pairs: List[str]) -> Dict[str, List[str]]: + """Return {family: [target, ...]}, both sorted.""" + seen = set() + families: Dict[str, List[str]] = {} + for pair in pairs: + name, _, family = pair.partition("=") + if not name or not C_IDENT.match(family) or name in seen: + sys.exit(f"{sys.argv[0]}: bad or duplicate --target '{pair}'") + seen.add(name) + families.setdefault(family, []).append(name) + return {f: sorted(t) for f, t in sorted(families.items())} + + +def write(path: str, lines: List[str]) -> None: + with open(path, "w", encoding="utf-8", newline="\n") as fh: + fh.write("\n".join([HEADER, ""] + lines + [""])) + + +def predicate(fn: str, cases: List[str]) -> List[str]: + body = ([" switch (ti->target_arch) {"] + + [f" case {c}:" for c in cases] + + [" return true;", " default:", + " return false;", " }"]) + return [f"bool target_is_{fn}(const TargetInfo *ti)", "{", *body, "}", + "", f"bool target_{fn}(void)", "{", + f" return target_is_{fn}(target_info());", "}", ""] + + +def main() -> None: + parser = argparse.ArgumentParser(description=__doc__.split("\n")[0]) + parser.add_argument("--target", action="append", required=True, + metavar="NAME=TARGET_BASE_ARCH") + parser.add_argument("outdir") + args = parser.parse_args() + families = parse_targets(args.target) + + # (helper suffix, QOM name, enum constants, parent macro or None) + entries = [] + for family, targets in families.items(): + consts = [c_enum_const("SysEmuTarget", t) for t in targets] + entries.append((f"base_{family}", f"target-base-{family}", + consts, None)) + for family, targets in families.items(): + for t in targets: + entries.append((c_name(t, False), f"target-{t}", + [c_enum_const("SysEmuTarget", t)], + f"TYPE_TARGET_BASE_{family.upper()}_MACHINE")) + + def macro(fn: str) -> str: + return f"TYPE_TARGET_{fn.upper()}_MACHINE" + + header = ["#ifndef TARGET_INFO_GEN_H", "#define TARGET_INFO_GEN_H", "", + "typedef struct TargetInfo TargetInfo;", ""] + for fn, _, _, _ in entries: + header += [f"bool target_is_{fn}(const TargetInfo *ti);", + f"bool target_{fn}(void);", ""] + write(os.path.join(args.outdir, "target-info-gen.h"), + header + ["#endif"]) + + source = [] + for fn, _, consts, _ in entries: + source += predicate(fn, consts) + write(os.path.join(args.outdir, "target-info-gen.c.inc"), source) + +if __name__ == "__main__": + main() diff --git a/target-info.c b/target-info.c index 8ccb333e365..fec8ee7c08e 100644 --- a/target-info.c +++ b/target-info.c @@ -101,64 +101,4 @@ bool target_big_endian(void) return target_endian_mode() == ENDIAN_MODE_BIG; } -bool target_base_arm(void) -{ - switch (target_arch()) { - case SYS_EMU_TARGET_ARM: - case SYS_EMU_TARGET_AARCH64: - return true; - default: - return false; - } -} - -bool target_arm(void) -{ - return target_arch() == SYS_EMU_TARGET_ARM; -} - -bool target_aarch64(void) -{ - return target_arch() == SYS_EMU_TARGET_AARCH64; -} - -bool target_m68k(void) -{ - return target_arch() == SYS_EMU_TARGET_M68K; -} - -bool target_or1k(void) -{ - return target_arch() == SYS_EMU_TARGET_OR1K; -} - -bool target_base_ppc(void) -{ - switch (target_arch()) { - case SYS_EMU_TARGET_PPC: - case SYS_EMU_TARGET_PPC64: - return true; - default: - return false; - } -} - -bool target_ppc(void) -{ - return target_arch() == SYS_EMU_TARGET_PPC; -} - -bool target_ppc64(void) -{ - return target_arch() == SYS_EMU_TARGET_PPC64; -} - -bool target_s390x(void) -{ - return target_arch() == SYS_EMU_TARGET_S390X; -} - -bool target_riscv64(void) -{ - return target_arch() == SYS_EMU_TARGET_RISCV64; -} +#include "target-info-gen.c.inc" -- 2.55.0.windows.3
