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


Reply via email to