[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[RFC v3 06/32] scripts/qapi: add a CABI module
From: |
marcandre . lureau |
Subject: |
[RFC v3 06/32] scripts/qapi: add a CABI module |
Date: |
Tue, 7 Sep 2021 16:19:17 +0400 |
From: Marc-André Lureau <marcandre.lureau@redhat.com>
This module will help to build C ABI tests for both Rust and C QAPI
generated types.
Currently, it will simply print basic struct layout (size and offset of
members) and the enum size and maximum values. By diffing the output, it
will help to ensure that the Rust definition is compatible with the C
version, including with configuration specifics.
Example output:
GuestDeviceAddress struct: sizeof=16
type member: sizeof=4 offset=0
GuestDeviceAddressKind enum: sizeof=4
max=1
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
meson.build | 1 +
scripts/qapi/cabi.py | 137 +++++++++++++++++++++++++++++++++++++++++++
2 files changed, 138 insertions(+)
create mode 100644 scripts/qapi/cabi.py
diff --git a/meson.build b/meson.build
index 6e871af4d0..cbf3ce19ae 100644
--- a/meson.build
+++ b/meson.build
@@ -1966,6 +1966,7 @@ hxtool = find_program('scripts/hxtool')
shaderinclude = find_program('scripts/shaderinclude.pl')
qapi_gen = find_program('scripts/qapi-gen.py')
qapi_gen_depends = [ meson.source_root() / 'scripts/qapi/__init__.py',
+ meson.source_root() / 'scripts/qapi/cabi.py',
meson.source_root() / 'scripts/qapi/commands.py',
meson.source_root() / 'scripts/qapi/common.py',
meson.source_root() / 'scripts/qapi/error.py',
diff --git a/scripts/qapi/cabi.py b/scripts/qapi/cabi.py
new file mode 100644
index 0000000000..f33680477f
--- /dev/null
+++ b/scripts/qapi/cabi.py
@@ -0,0 +1,137 @@
+#
+# QAPI helper library
+# C ABI verification test generator
+#
+# pylint: disable=too-few-public-methods
+
+from typing import List, Optional
+
+from .common import c_enum_const, c_name, mcgen
+from .schema import (
+ QAPISchemaEnumMember,
+ QAPISchemaIfCond,
+ QAPISchemaObjectType,
+ QAPISchemaObjectTypeMember,
+ QAPISchemaVariants,
+)
+
+
+class CABI:
+ def __init__(self, name: str, ifcond: QAPISchemaIfCond):
+ self.name = name
+ self.ifcond = ifcond
+
+ def gen_c(self) -> str:
+ raise NotImplementedError()
+
+
+class CABIEnum(CABI):
+ def __init__(
+ self,
+ name: str,
+ ifcond: QAPISchemaIfCond,
+ members: List[QAPISchemaEnumMember],
+ prefix: Optional[str] = None,
+ ):
+ super().__init__(name, ifcond)
+ self.members = members
+ self.prefix = prefix
+
+ def gen_c(self) -> str:
+ last = c_enum_const(self.name, "_MAX", self.prefix)
+ ret = self.ifcond.gen_if()
+ ret += mcgen("""
+ printf("%(name)s enum: sizeof=%%zu\\n", sizeof(%(cname)s));
+ printf(" max=%%d\\n", %(last)s);
+ printf("\\n");
+""", name=self.name, cname=c_name(self.name), last=last)
+ ret += self.ifcond.gen_endif()
+ return ret
+
+
+class CABIStruct(CABI):
+ def __init__(self, name: str, ifcond: QAPISchemaIfCond):
+ super().__init__(name, ifcond)
+ self.members: List[CABIStructMember] = []
+
+ def add_members(self, members: List[QAPISchemaObjectTypeMember]) -> None:
+ for memb in members:
+ if memb.optional:
+ self.add_member(memb.name, memb.ifcond, "has_")
+ self.add_member(memb.name, memb.ifcond)
+
+ def add_variants(self, variants: QAPISchemaVariants) -> None:
+ for var in variants.variants:
+ if var.type.name == "q_empty":
+ continue
+ self.add_member(var.name, var.ifcond, "u.")
+
+ def add_member(self, member: str,
+ ifcond: Optional[QAPISchemaIfCond] = None,
+ prefix: str = '') -> None:
+ self.members.append(CABIStructMember(self, member, ifcond, prefix))
+
+ def gen_c(self) -> str:
+ ret = self.ifcond.gen_if()
+ ret += mcgen("""
+ printf("%(name)s struct: sizeof=%%zu\\n", sizeof(%(name)s));
+""", name=self.name)
+ for member in self.members:
+ ret += member.gen_c()
+ ret += mcgen("""
+ printf("\\n");
+""")
+ ret += self.ifcond.gen_endif()
+ return ret
+
+
+class CABIStructMember:
+ def __init__(self, struct: CABIStruct, name: str,
+ ifcond: Optional[QAPISchemaIfCond] = None,
+ prefix: str = ''):
+ self.struct = struct
+ self.name = name
+ self.ifcond = ifcond or QAPISchemaIfCond()
+ self.prefix = prefix
+
+ def gen_c(self) -> str:
+ ret = self.ifcond.gen_if()
+ cmember = self.prefix + c_name(self.name)
+ ret += mcgen("""
+ printf(" %(member)s member: sizeof=%%zu offset=%%zu\\n",
+ G_SIZEOF_MEMBER(struct %(sname)s, %(cmember)s),
+ offsetof(struct %(sname)s, %(cmember)s));
+""", member=self.name, sname=self.struct.name, cmember=cmember)
+ ret += self.ifcond.gen_endif()
+ return ret
+
+
+def gen_object_cabi(
+ name: str,
+ ifcond: QAPISchemaIfCond,
+ base: Optional[QAPISchemaObjectType],
+ members: List[QAPISchemaObjectTypeMember],
+ variants: Optional[QAPISchemaVariants],
+) -> List[CABI]:
+ if name == 'q_empty':
+ return []
+ ret = []
+ for var in variants.variants if variants else ():
+ obj = var.type
+ if not isinstance(obj, QAPISchemaObjectType):
+ continue
+ ret.extend(
+ gen_object_cabi(
+ obj.name, obj.ifcond, obj.base, obj.local_members, obj.variants
+ )
+ )
+ cabi = CABIStruct(c_name(name), ifcond)
+ if base:
+ cabi.add_members(base.members)
+ cabi.add_members(members)
+ if variants:
+ cabi.add_variants(variants)
+ if (not base or base.is_empty()) and not members and not variants:
+ cabi.add_member('qapi_dummy_for_empty_struct')
+ ret.append(cabi)
+ return ret
--
2.33.0.113.g6c40894d24
- Re: [RFC v3 02/32] build-sys: add HAVE_IPPROTO_MPTCP, (continued)
- [RFC v3 03/32] scripts/qapi: teach c_param_type() to return const argument type, marcandre . lureau, 2021/09/07
- [RFC v3 04/32] glib-compat: add G_SIZEOF_MEMBER, marcandre . lureau, 2021/09/07
- [RFC v3 05/32] scripts/qapi: add QAPISchemaVisitor.visit_module_end, marcandre . lureau, 2021/09/07
- [RFC v3 06/32] scripts/qapi: add a CABI module,
marcandre . lureau <=
- [RFC v3 07/32] scripts/qapi: generate CABI dump for C types, marcandre . lureau, 2021/09/07
- [RFC v3 08/32] tests: build qapi-cabi (C ABI dump), marcandre . lureau, 2021/09/07
- [RFC v3 09/32] build-sys: add i686 cpu target, marcandre . lureau, 2021/09/07
- [RFC v3 10/32] build-sys: add --with-rust{-target} & basic build infrastructure, marcandre . lureau, 2021/09/07
- [RFC v3 11/32] build-sys: add a cargo-wrapper script, marcandre . lureau, 2021/09/07
- [RFC v3 12/32] rust: provide a common crate for QEMU, marcandre . lureau, 2021/09/07