From b513481b9a6bac8413dead13287106d0bf50f996 Mon Sep 17 00:00:00 2001 From: Eric Blake Date: Tue, 20 Feb 2018 16:02:25 -0500 Subject: [PATCH] qapi: Emit structs used as variants in topological order Right now, we emit the branches of union types as a boxed pointer, and it suffices to have a forward declaration of the type. However, a future patch will swap things to directly use the branch type, instead of hiding it behind a pointer. For this to work, the compiler needs the full definition of the type, not just a forward declaration, prior to the union that is including the branch type. This patch just adds topological sorting to hoist all types mentioned in a branch of a union to be fully declared before the union itself. The sort is always possible, because we do not allow circular union types that include themselves as a direct branch (it is, however, still possible to include a branch type that itself has a pointer to the union, for a type that can indirectly recursively nest itself - that remains safe, because that the member of the branch type will remain a pointer, and the QMP representation of such a type adds another {} for each recurring layer of the union type). Backports commit 1de5d4ca0752138034305f3d4e8fe17ef6503569 from qemu --- qemu/scripts/qapi-types.py | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/qemu/scripts/qapi-types.py b/qemu/scripts/qapi-types.py index 09573ad7..ebc0f662 100644 --- a/qemu/scripts/qapi-types.py +++ b/qemu/scripts/qapi-types.py @@ -2,7 +2,7 @@ # QAPI types generator # # Copyright IBM, Corp. 2011 -# Copyright (c) 2013-2015 Red Hat Inc. +# Copyright (c) 2013-2016 Red Hat Inc. # # Authors: # Anthony Liguori @@ -13,6 +13,10 @@ from qapi import * +# variants must be emitted before their container; track what has already +# been output +objects_seen = set() + def gen_fwd_object_or_array(name): return mcgen(''' @@ -51,11 +55,23 @@ def gen_struct_fields(members): def gen_object(name, base, members, variants): - ret = mcgen(''' + if name in objects_seen: + return '' + objects_seen.add(name) + + ret = '' + if variants: + for v in variants.variants: + if (isinstance(v.type, QAPISchemaObjectType) and + not v.type.is_implicit()): + ret += gen_object(v.type.name, v.type.base, + v.type.local_members, v.type.variants) + + ret += mcgen(''' struct %(c_name)s { ''', - c_name=c_name(name)) + c_name=c_name(name)) if base: ret += mcgen('''