From nobody Wed Sep 10 00:40:25 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1631017578594257.6962597480941; Tue, 7 Sep 2021 05:26:18 -0700 (PDT) Received: from localhost ([::1]:45392 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mNaB7-0007ax-Ho for importer@patchew.org; Tue, 07 Sep 2021 08:26:17 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:42116) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mNa6J-0007ej-8T for qemu-devel@nongnu.org; Tue, 07 Sep 2021 08:21:19 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]:40450) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mNa6G-0006gQ-IW for qemu-devel@nongnu.org; Tue, 07 Sep 2021 08:21:18 -0400 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-436-lo3dDzczOC-GVelyvUgisA-1; Tue, 07 Sep 2021 08:21:11 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 99A806D58F for ; Tue, 7 Sep 2021 12:21:10 +0000 (UTC) Received: from localhost (unknown [10.39.208.23]) by smtp.corp.redhat.com (Postfix) with ESMTP id 2801C5D6CF; Tue, 7 Sep 2021 12:20:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1631017276; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=MdWjztreNk1HSfZb6qrkgsYAfbyLwZ8/w91WuKIhg24=; b=KJ+Pw2PtuEXXINPk8XnHXcrl8fNXDaeEtCVIfDN3IHTpQ2ZKxdwFawrcZ3KdyoE2VXuTBj o/6xxTztHutU2G1A09rp7uK/aa1JIPrf0DxzZ6o2QXXp4hSlx8KptPlAPsToq/UrjB3Qw0 6io5GpyfJfUzOAB3DHEmwVnGtP1Ok9U= X-MC-Unique: lo3dDzczOC-GVelyvUgisA-1 From: marcandre.lureau@redhat.com To: qemu-devel@nongnu.org Subject: [RFC v3 06/32] scripts/qapi: add a CABI module Date: Tue, 7 Sep 2021 16:19:17 +0400 Message-Id: <20210907121943.3498701-7-marcandre.lureau@redhat.com> In-Reply-To: <20210907121943.3498701-1-marcandre.lureau@redhat.com> References: <20210907121943.3498701-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=marcandre.lureau@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.133.124; envelope-from=marcandre.lureau@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -31 X-Spam_score: -3.2 X-Spam_bar: --- X-Spam_report: (-3.2 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.391, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_MSPIKE_H2=-0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: pbonzini@redhat.com, berrange@redhat.com, armbru@redhat.com, stefanha@redhat.com, =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZM-MESSAGEID: 1631017580740100001 From: Marc-Andr=C3=A9 Lureau 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=3D16 type member: sizeof=3D4 offset=3D0 GuestDeviceAddressKind enum: sizeof=3D4 max=3D1 Signed-off-by: Marc-Andr=C3=A9 Lureau --- 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 =3D find_program('scripts/hxtool') shaderinclude =3D find_program('scripts/shaderinclude.pl') qapi_gen =3D find_program('scripts/qapi-gen.py') qapi_gen_depends =3D [ 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=3Dtoo-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 =3D name + self.ifcond =3D ifcond + + def gen_c(self) -> str: + raise NotImplementedError() + + +class CABIEnum(CABI): + def __init__( + self, + name: str, + ifcond: QAPISchemaIfCond, + members: List[QAPISchemaEnumMember], + prefix: Optional[str] =3D None, + ): + super().__init__(name, ifcond) + self.members =3D members + self.prefix =3D prefix + + def gen_c(self) -> str: + last =3D c_enum_const(self.name, "_MAX", self.prefix) + ret =3D self.ifcond.gen_if() + ret +=3D mcgen(""" + printf("%(name)s enum: sizeof=3D%%zu\\n", sizeof(%(cname)s)); + printf(" max=3D%%d\\n", %(last)s); + printf("\\n"); +""", name=3Dself.name, cname=3Dc_name(self.name), last=3Dlast) + ret +=3D self.ifcond.gen_endif() + return ret + + +class CABIStruct(CABI): + def __init__(self, name: str, ifcond: QAPISchemaIfCond): + super().__init__(name, ifcond) + self.members: List[CABIStructMember] =3D [] + + def add_members(self, members: List[QAPISchemaObjectTypeMember]) -> No= ne: + 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 =3D=3D "q_empty": + continue + self.add_member(var.name, var.ifcond, "u.") + + def add_member(self, member: str, + ifcond: Optional[QAPISchemaIfCond] =3D None, + prefix: str =3D '') -> None: + self.members.append(CABIStructMember(self, member, ifcond, prefix)) + + def gen_c(self) -> str: + ret =3D self.ifcond.gen_if() + ret +=3D mcgen(""" + printf("%(name)s struct: sizeof=3D%%zu\\n", sizeof(%(name)s)); +""", name=3Dself.name) + for member in self.members: + ret +=3D member.gen_c() + ret +=3D mcgen(""" + printf("\\n"); +""") + ret +=3D self.ifcond.gen_endif() + return ret + + +class CABIStructMember: + def __init__(self, struct: CABIStruct, name: str, + ifcond: Optional[QAPISchemaIfCond] =3D None, + prefix: str =3D ''): + self.struct =3D struct + self.name =3D name + self.ifcond =3D ifcond or QAPISchemaIfCond() + self.prefix =3D prefix + + def gen_c(self) -> str: + ret =3D self.ifcond.gen_if() + cmember =3D self.prefix + c_name(self.name) + ret +=3D mcgen(""" + printf(" %(member)s member: sizeof=3D%%zu offset=3D%%zu\\n", + G_SIZEOF_MEMBER(struct %(sname)s, %(cmember)s), + offsetof(struct %(sname)s, %(cmember)s)); +""", member=3Dself.name, sname=3Dself.struct.name, cmember=3Dcmember) + ret +=3D 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 =3D=3D 'q_empty': + return [] + ret =3D [] + for var in variants.variants if variants else (): + obj =3D var.type + if not isinstance(obj, QAPISchemaObjectType): + continue + ret.extend( + gen_object_cabi( + obj.name, obj.ifcond, obj.base, obj.local_members, obj.var= iants + ) + ) + cabi =3D 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 --=20 2.33.0.113.g6c40894d24