2018-02-11 10:35:41 +01:00
|
|
|
"""
|
|
|
|
QAPI types generator
|
|
|
|
|
|
|
|
Copyright IBM, Corp. 2011
|
|
|
|
Copyright (c) 2013-2018 Red Hat Inc.
|
|
|
|
|
|
|
|
Authors:
|
|
|
|
Anthony Liguori <aliguori@us.ibm.com>
|
|
|
|
Michael Roth <mdroth@linux.vnet.ibm.com>
|
|
|
|
Markus Armbruster <armbru@redhat.com>
|
|
|
|
|
|
|
|
This work is licensed under the terms of the GNU GPL, version 2.
|
2014-03-01 08:40:34 +01:00
|
|
|
# See the COPYING file in the top-level directory.
|
2018-02-11 10:35:41 +01:00
|
|
|
"""
|
2011-07-19 21:50:40 +02:00
|
|
|
|
2021-08-04 10:30:57 +02:00
|
|
|
from typing import List, Optional
|
2020-10-09 18:15:54 +02:00
|
|
|
|
2021-08-31 14:37:58 +02:00
|
|
|
from .common import c_enum_const, c_name, mcgen
|
2022-02-11 19:36:50 +01:00
|
|
|
from .gen import (
|
|
|
|
QAPISchemaModularCVisitor,
|
|
|
|
gen_special_features,
|
|
|
|
ifcontext,
|
|
|
|
)
|
2020-10-09 18:15:54 +02:00
|
|
|
from .schema import (
|
|
|
|
QAPISchema,
|
|
|
|
QAPISchemaEnumMember,
|
|
|
|
QAPISchemaFeature,
|
2021-08-04 10:30:57 +02:00
|
|
|
QAPISchemaIfCond,
|
2020-10-09 18:15:54 +02:00
|
|
|
QAPISchemaObjectType,
|
|
|
|
QAPISchemaObjectTypeMember,
|
|
|
|
QAPISchemaType,
|
|
|
|
QAPISchemaVariants,
|
|
|
|
)
|
|
|
|
from .source import QAPISourceInfo
|
2011-07-19 21:50:40 +02:00
|
|
|
|
2015-09-16 13:06:16 +02:00
|
|
|
|
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).
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1455778109-6278-11-git-send-email-eblake@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-02-18 07:48:24 +01:00
|
|
|
# variants must be emitted before their container; track what has already
|
|
|
|
# been output
|
|
|
|
objects_seen = set()
|
|
|
|
|
|
|
|
|
2020-10-09 18:15:54 +02:00
|
|
|
def gen_enum_lookup(name: str,
|
|
|
|
members: List[QAPISchemaEnumMember],
|
|
|
|
prefix: Optional[str] = None) -> str:
|
2021-10-25 06:24:04 +02:00
|
|
|
max_index = c_enum_const(name, '_MAX', prefix)
|
2021-10-28 12:25:18 +02:00
|
|
|
feats = ''
|
2019-10-18 09:43:43 +02:00
|
|
|
ret = mcgen('''
|
|
|
|
|
|
|
|
const QEnumLookup %(c_name)s_lookup = {
|
|
|
|
.array = (const char *const[]) {
|
|
|
|
''',
|
|
|
|
c_name=c_name(name))
|
2020-10-09 18:15:55 +02:00
|
|
|
for memb in members:
|
2021-08-31 14:37:58 +02:00
|
|
|
ret += memb.ifcond.gen_if()
|
2020-10-09 18:15:55 +02:00
|
|
|
index = c_enum_const(name, memb.name, prefix)
|
2019-10-18 09:43:43 +02:00
|
|
|
ret += mcgen('''
|
|
|
|
[%(index)s] = "%(name)s",
|
|
|
|
''',
|
2020-10-09 18:15:55 +02:00
|
|
|
index=index, name=memb.name)
|
2021-08-31 14:37:58 +02:00
|
|
|
ret += memb.ifcond.gen_endif()
|
2021-10-28 12:25:18 +02:00
|
|
|
|
|
|
|
special_features = gen_special_features(memb.features)
|
|
|
|
if special_features != '0':
|
|
|
|
feats += mcgen('''
|
|
|
|
[%(index)s] = %(special_features)s,
|
2021-10-25 06:24:04 +02:00
|
|
|
''',
|
2021-10-28 12:25:18 +02:00
|
|
|
index=index, special_features=special_features)
|
2021-10-25 06:24:04 +02:00
|
|
|
|
2021-10-28 12:25:18 +02:00
|
|
|
if feats:
|
2021-10-25 06:24:04 +02:00
|
|
|
ret += mcgen('''
|
|
|
|
},
|
2021-10-28 12:25:18 +02:00
|
|
|
.special_features = (const unsigned char[%(max_index)s]) {
|
2021-10-25 06:24:04 +02:00
|
|
|
''',
|
|
|
|
max_index=max_index)
|
2021-10-28 12:25:18 +02:00
|
|
|
ret += feats
|
2019-10-18 09:43:43 +02:00
|
|
|
|
|
|
|
ret += mcgen('''
|
|
|
|
},
|
|
|
|
.size = %(max_index)s
|
|
|
|
};
|
|
|
|
''',
|
2021-10-25 06:24:04 +02:00
|
|
|
max_index=max_index)
|
2019-10-18 09:43:43 +02:00
|
|
|
return ret
|
|
|
|
|
|
|
|
|
2020-10-09 18:15:54 +02:00
|
|
|
def gen_enum(name: str,
|
|
|
|
members: List[QAPISchemaEnumMember],
|
|
|
|
prefix: Optional[str] = None) -> str:
|
2019-10-18 09:43:43 +02:00
|
|
|
# append automatically generated _MAX value
|
|
|
|
enum_members = members + [QAPISchemaEnumMember('_MAX', None)]
|
|
|
|
|
|
|
|
ret = mcgen('''
|
|
|
|
|
|
|
|
typedef enum %(c_name)s {
|
|
|
|
''',
|
|
|
|
c_name=c_name(name))
|
|
|
|
|
2020-10-09 18:15:55 +02:00
|
|
|
for memb in enum_members:
|
2021-08-31 14:37:58 +02:00
|
|
|
ret += memb.ifcond.gen_if()
|
2019-10-18 09:43:43 +02:00
|
|
|
ret += mcgen('''
|
|
|
|
%(c_enum)s,
|
|
|
|
''',
|
2020-10-09 18:15:55 +02:00
|
|
|
c_enum=c_enum_const(name, memb.name, prefix))
|
2021-08-31 14:37:58 +02:00
|
|
|
ret += memb.ifcond.gen_endif()
|
2019-10-18 09:43:43 +02:00
|
|
|
|
|
|
|
ret += mcgen('''
|
|
|
|
} %(c_name)s;
|
|
|
|
''',
|
|
|
|
c_name=c_name(name))
|
|
|
|
|
|
|
|
ret += mcgen('''
|
|
|
|
|
|
|
|
#define %(c_name)s_str(val) \\
|
|
|
|
qapi_enum_lookup(&%(c_name)s_lookup, (val))
|
|
|
|
|
|
|
|
extern const QEnumLookup %(c_name)s_lookup;
|
|
|
|
''',
|
|
|
|
c_name=c_name(name))
|
|
|
|
return ret
|
|
|
|
|
|
|
|
|
2020-10-09 18:15:54 +02:00
|
|
|
def gen_fwd_object_or_array(name: str) -> str:
|
2011-07-19 21:50:40 +02:00
|
|
|
return mcgen('''
|
2013-05-11 00:46:00 +02:00
|
|
|
|
2015-09-16 13:06:16 +02:00
|
|
|
typedef struct %(c_name)s %(c_name)s;
|
2011-07-19 21:50:40 +02:00
|
|
|
''',
|
2015-09-16 13:06:16 +02:00
|
|
|
c_name=c_name(name))
|
|
|
|
|
2011-07-19 21:50:40 +02:00
|
|
|
|
2020-10-09 18:15:54 +02:00
|
|
|
def gen_array(name: str, element_type: QAPISchemaType) -> str:
|
qapi: generate list struct and visit_list for enum
Currently, if we define an 'enum' and use it in one command's
data, list struct for enum could not be generated, but it's
used in qmp function.
For example: KeyCodesList could not be generated.
>>> qapi-schema.json:
{ 'enum': 'KeyCodes',
'data': [ 'shift', 'alt' ... ] }
{ 'command': 'sendkey',
'data': { 'keys': ['KeyCodes'], '*hold-time': 'int' } }
>>> qmp-command.h:
void qmp_sendkey(KeyCodesList * keys, bool has_hold_time, int64_t
hold_time, Error **errp);
This patch lets qapi generate list struct and visit_list for enum.
Signed-off-by: Amos Kong <akong@redhat.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
2012-08-31 04:56:23 +02:00
|
|
|
return mcgen('''
|
2015-07-01 16:55:15 +02:00
|
|
|
|
2015-09-16 13:06:16 +02:00
|
|
|
struct %(c_name)s {
|
|
|
|
%(c_name)s *next;
|
qapi: Adjust layout of FooList types
By sticking the next pointer first, we don't need a union with
64-bit padding for smaller types. On 32-bit platforms, this
can reduce the size of uint8List from 16 bytes (or 12, depending
on whether 64-bit ints can tolerate 4-byte alignment) down to 8.
It has no effect on 64-bit platforms (where alignment still
dictates a 16-byte struct); but fewer anonymous unions is still
a win in my book.
It requires visit_next_list() to gain a size parameter, to know
what size element to allocate; comparable to the size parameter
of visit_start_struct().
I debated about going one step further, to allow for fewer casts,
by doing:
typedef GenericList GenericList;
struct GenericList {
GenericList *next;
};
struct FooList {
GenericList base;
Foo *value;
};
so that you convert to 'GenericList *' by '&foolist->base', and
back by 'container_of(generic, GenericList, base)' (as opposed to
the existing '(GenericList *)foolist' and '(FooList *)generic').
But doing that would require hoisting the declaration of
GenericList prior to inclusion of qapi-types.h, rather than its
current spot in visitor.h; it also makes iteration a bit more
verbose through 'foolist->base.next' instead of 'foolist->next'.
Note that for lists of objects, the 'value' payload is still
hidden behind a boxed pointer. Someday, it would be nice to do:
struct FooList {
FooList *next;
Foo value;
};
for one less level of malloc for each list element. This patch
is a step in that direction (now that 'next' is no longer at a
fixed non-zero offset within the struct, we can store more than
just a pointer's-worth of data as the value payload), but the
actual conversion would be a task for another series, as it will
touch a lot of code.
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1455778109-6278-10-git-send-email-eblake@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-02-18 07:48:23 +01:00
|
|
|
%(c_type)s value;
|
qapi-types: Convert to QAPISchemaVisitor, fixing flat unions
Fixes flat unions to get the base's base members. Test case is from
commit 2fc0043, in qapi-schema-test.json:
{ 'union': 'UserDefFlatUnion',
'base': 'UserDefUnionBase',
'discriminator': 'enum1',
'data': { 'value1' : 'UserDefA',
'value2' : 'UserDefB',
'value3' : 'UserDefB' } }
{ 'struct': 'UserDefUnionBase',
'base': 'UserDefZero',
'data': { 'string': 'str', 'enum1': 'EnumOne' } }
{ 'struct': 'UserDefZero',
'data': { 'integer': 'int' } }
Patch's effect on UserDefFlatUnion:
struct UserDefFlatUnion {
/* Members inherited from UserDefUnionBase: */
+ int64_t integer;
char *string;
EnumOne enum1;
/* Own members: */
union { /* union tag is @enum1 */
void *data;
UserDefA *value1;
UserDefB *value2;
UserDefB *value3;
};
};
Flat union visitors remain broken. They'll be fixed next.
Code is generated in a different order now, but that doesn't matter.
The two guards QAPI_TYPES_BUILTIN_STRUCT_DECL and
QAPI_TYPES_BUILTIN_CLEANUP_DECL are replaced by just
QAPI_TYPES_BUILTIN.
Two ugly special cases for simple unions now stand out like sore
thumbs:
1. The type tag is named 'type' everywhere, except in generated C,
where it's 'kind'.
2. QAPISchema lowers simple unions to semantically equivalent flat
unions. However, the C generated for a simple unions differs from
the C generated for its equivalent flat union, and we therefore
need special code to preserve that pointless difference for now.
Mark both TODO.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
2015-09-16 13:06:09 +02:00
|
|
|
};
|
qapi: generate list struct and visit_list for enum
Currently, if we define an 'enum' and use it in one command's
data, list struct for enum could not be generated, but it's
used in qmp function.
For example: KeyCodesList could not be generated.
>>> qapi-schema.json:
{ 'enum': 'KeyCodes',
'data': [ 'shift', 'alt' ... ] }
{ 'command': 'sendkey',
'data': { 'keys': ['KeyCodes'], '*hold-time': 'int' } }
>>> qmp-command.h:
void qmp_sendkey(KeyCodesList * keys, bool has_hold_time, int64_t
hold_time, Error **errp);
This patch lets qapi generate list struct and visit_list for enum.
Signed-off-by: Amos Kong <akong@redhat.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
2012-08-31 04:56:23 +02:00
|
|
|
''',
|
2015-09-16 13:06:16 +02:00
|
|
|
c_name=c_name(name), c_type=element_type.c_type())
|
|
|
|
|
qapi: generate list struct and visit_list for enum
Currently, if we define an 'enum' and use it in one command's
data, list struct for enum could not be generated, but it's
used in qmp function.
For example: KeyCodesList could not be generated.
>>> qapi-schema.json:
{ 'enum': 'KeyCodes',
'data': [ 'shift', 'alt' ... ] }
{ 'command': 'sendkey',
'data': { 'keys': ['KeyCodes'], '*hold-time': 'int' } }
>>> qmp-command.h:
void qmp_sendkey(KeyCodesList * keys, bool has_hold_time, int64_t
hold_time, Error **errp);
This patch lets qapi generate list struct and visit_list for enum.
Signed-off-by: Amos Kong <akong@redhat.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
2012-08-31 04:56:23 +02:00
|
|
|
|
2020-10-09 18:15:54 +02:00
|
|
|
def gen_struct_members(members: List[QAPISchemaObjectTypeMember]) -> str:
|
2013-07-02 12:18:18 +02:00
|
|
|
ret = ''
|
2015-11-18 09:52:38 +01:00
|
|
|
for memb in members:
|
2021-08-31 14:37:58 +02:00
|
|
|
ret += memb.ifcond.gen_if()
|
2015-11-18 09:52:38 +01:00
|
|
|
if memb.optional:
|
|
|
|
ret += mcgen('''
|
2011-07-19 21:50:40 +02:00
|
|
|
bool has_%(c_name)s;
|
|
|
|
''',
|
2015-11-18 09:52:38 +01:00
|
|
|
c_name=c_name(memb.name))
|
|
|
|
ret += mcgen('''
|
2011-07-19 21:50:40 +02:00
|
|
|
%(c_type)s %(c_name)s;
|
|
|
|
''',
|
2015-11-18 09:52:38 +01:00
|
|
|
c_type=memb.type.c_type(), c_name=c_name(memb.name))
|
2021-08-31 14:37:58 +02:00
|
|
|
ret += memb.ifcond.gen_endif()
|
2013-07-02 12:18:18 +02:00
|
|
|
return ret
|
|
|
|
|
2015-09-16 13:06:16 +02:00
|
|
|
|
2021-08-04 10:30:57 +02:00
|
|
|
def gen_object(name: str, ifcond: QAPISchemaIfCond,
|
2020-10-09 18:15:54 +02:00
|
|
|
base: Optional[QAPISchemaObjectType],
|
|
|
|
members: List[QAPISchemaObjectTypeMember],
|
|
|
|
variants: Optional[QAPISchemaVariants]) -> str:
|
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).
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1455778109-6278-11-git-send-email-eblake@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-02-18 07:48:24 +01:00
|
|
|
if name in objects_seen:
|
|
|
|
return ''
|
|
|
|
objects_seen.add(name)
|
|
|
|
|
|
|
|
ret = ''
|
2020-10-09 18:15:55 +02:00
|
|
|
for var in variants.variants if variants else ():
|
|
|
|
obj = var.type
|
|
|
|
if not isinstance(obj, QAPISchemaObjectType):
|
|
|
|
continue
|
|
|
|
ret += gen_object(obj.name, obj.ifcond, obj.base,
|
|
|
|
obj.local_members, obj.variants)
|
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).
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1455778109-6278-11-git-send-email-eblake@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-02-18 07:48:24 +01:00
|
|
|
|
|
|
|
ret += mcgen('''
|
2015-11-18 09:52:38 +01:00
|
|
|
|
2018-07-03 17:56:45 +02:00
|
|
|
''')
|
2021-08-31 14:37:58 +02:00
|
|
|
ret += ifcond.gen_if()
|
2018-07-03 17:56:45 +02:00
|
|
|
ret += mcgen('''
|
2015-11-18 09:52:38 +01:00
|
|
|
struct %(c_name)s {
|
|
|
|
''',
|
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).
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1455778109-6278-11-git-send-email-eblake@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-02-18 07:48:24 +01:00
|
|
|
c_name=c_name(name))
|
2013-09-18 17:22:02 +02:00
|
|
|
|
2015-10-26 23:34:47 +01:00
|
|
|
if base:
|
2016-03-17 23:48:39 +01:00
|
|
|
if not base.is_implicit():
|
|
|
|
ret += mcgen('''
|
2015-10-26 23:34:47 +01:00
|
|
|
/* Members inherited from %(c_name)s: */
|
|
|
|
''',
|
2016-03-17 23:48:39 +01:00
|
|
|
c_name=base.c_name())
|
2016-03-03 17:16:43 +01:00
|
|
|
ret += gen_struct_members(base.members)
|
2016-03-17 23:48:39 +01:00
|
|
|
if not base.is_implicit():
|
|
|
|
ret += mcgen('''
|
2015-10-26 23:34:47 +01:00
|
|
|
/* Own members: */
|
|
|
|
''')
|
2016-03-03 17:16:43 +01:00
|
|
|
ret += gen_struct_members(members)
|
2013-07-02 12:18:18 +02:00
|
|
|
|
2015-11-18 09:52:37 +01:00
|
|
|
if variants:
|
|
|
|
ret += gen_variants(variants)
|
|
|
|
|
2016-03-03 17:16:43 +01:00
|
|
|
# Make sure that all structs have at least one member; this avoids
|
2015-09-16 13:06:16 +02:00
|
|
|
# potential issues with attempting to malloc space for zero-length
|
|
|
|
# structs in C, and also incompatibility with C++ (where an empty
|
|
|
|
# struct is size 1).
|
2016-07-14 05:50:16 +02:00
|
|
|
if (not base or base.is_empty()) and not members and not variants:
|
2015-09-16 13:06:16 +02:00
|
|
|
ret += mcgen('''
|
2016-03-03 17:16:44 +01:00
|
|
|
char qapi_dummy_for_empty_struct;
|
2015-01-20 16:19:32 +01:00
|
|
|
''')
|
|
|
|
|
2011-07-19 21:50:40 +02:00
|
|
|
ret += mcgen('''
|
2015-06-12 09:45:55 +02:00
|
|
|
};
|
|
|
|
''')
|
2021-08-31 14:37:58 +02:00
|
|
|
ret += ifcond.gen_endif()
|
2011-07-19 21:50:40 +02:00
|
|
|
|
|
|
|
return ret
|
|
|
|
|
2015-09-16 13:06:16 +02:00
|
|
|
|
2020-10-09 18:15:54 +02:00
|
|
|
def gen_upcast(name: str, base: QAPISchemaObjectType) -> str:
|
qapi: Prefer typesafe upcasts to qapi base classes
A previous patch (commit 1e6c1616) made it possible to
directly cast from a qapi flat union type to its base type.
However, it requires the use of a C cast, which turns off
compiler type-safety checks. Fortunately, no such casts
exist, just yet.
Regardless, add inline type-safe wrappers named
qapi_FOO_base() for any union type FOO that has a base,
which can be used for a safer upcast, and enhance the
testsuite to cover the new functionality.
A future patch will extend the upcast support to structs,
where such conversions do exist already.
Note that C makes const-correct upcasts annoying because
it lacks overloads; these functions cast away const so that
they can accept user pointers whether const or not, and the
result in turn can be assigned to normal or const pointers.
Alternatively, this could have been done with macros, but
type-safe macros are hairy, and not worthwhile here.
This patch just adds upcasts. None of our code needed to
downcast from a base qapi class to a child. Also, in the
case of grandchildren (such as BlockdevOptionsQcow2), the
caller will need to call two functions to get to the inner
base (although it wouldn't be too hard to generate a
qapi_FOO_base_base() if desired). If a user changes qapi
to alter the base class hierarchy, such as going from
'A -> C' to 'A -> B -> C', it will change the type of
'qapi_C_base()', and the compiler will point out the places
that are affected by the new base.
One alternative was proposed, but was deemed too ugly to use
in practice: the generators could output redundant
information using anonymous types:
| struct Child {
| union {
| struct {
| Type1 parent_member1;
| Type2 parent_member2;
| };
| Parent base;
| };
| };
With that ugly proposal, for a given qapi type, obj->member
and obj->base.member would refer to the same storage; allowing
convenience in working with members without needing 'base.'
allowing typesafe upcast without needing a C cast by accessing
'&obj->base', and allowing downcasts from the parent back to
the child possible through container_of(obj, Child, base).
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1445898903-12082-10-git-send-email-eblake@redhat.com>
[Commit message tweaked]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2015-10-26 23:34:48 +01:00
|
|
|
# C makes const-correctness ugly. We have to cast away const to let
|
|
|
|
# this function work for both const and non-const obj.
|
|
|
|
return mcgen('''
|
|
|
|
|
|
|
|
static inline %(base)s *qapi_%(c_name)s_base(const %(c_name)s *obj)
|
|
|
|
{
|
|
|
|
return (%(base)s *)obj;
|
|
|
|
}
|
|
|
|
''',
|
|
|
|
c_name=c_name(name), base=base.c_name())
|
|
|
|
|
|
|
|
|
2020-10-09 18:15:54 +02:00
|
|
|
def gen_variants(variants: QAPISchemaVariants) -> str:
|
2015-11-18 09:52:37 +01:00
|
|
|
ret = mcgen('''
|
qapi: Generate a nicer struct for flat unions
The struct generated for a flat union is weird: the members of its
base are at the end, except for the union tag, which is at the
beginning.
Example: qapi-schema-test.json has
{ 'struct': 'UserDefUnionBase',
'data': { 'string': 'str', 'enum1': 'EnumOne' } }
{ 'union': 'UserDefFlatUnion',
'base': 'UserDefUnionBase',
'discriminator': 'enum1',
'data': { 'value1' : 'UserDefA',
'value2' : 'UserDefB',
'value3' : 'UserDefB' } }
We generate:
struct UserDefFlatUnion
{
EnumOne enum1;
union {
void *data;
UserDefA *value1;
UserDefB *value2;
UserDefB *value3;
};
char *string;
};
Change to put all base members at the beginning, unadulterated. Not
only is this easier to understand, it also permits casting the flat
union to its base, if that should become useful.
We now generate:
struct UserDefFlatUnion
{
/* Members inherited from UserDefUnionBase: */
char *string;
EnumOne enum1;
/* Own members: */
union { /* union tag is @enum1 */
void *data;
UserDefA *value1;
UserDefB *value2;
UserDefB *value3;
};
};
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
2015-06-28 20:05:53 +02:00
|
|
|
union { /* union tag is @%(c_name)s */
|
2011-07-19 21:50:40 +02:00
|
|
|
''',
|
2015-11-18 09:52:37 +01:00
|
|
|
c_name=c_name(variants.tag_member.name))
|
qapi-types: Convert to QAPISchemaVisitor, fixing flat unions
Fixes flat unions to get the base's base members. Test case is from
commit 2fc0043, in qapi-schema-test.json:
{ 'union': 'UserDefFlatUnion',
'base': 'UserDefUnionBase',
'discriminator': 'enum1',
'data': { 'value1' : 'UserDefA',
'value2' : 'UserDefB',
'value3' : 'UserDefB' } }
{ 'struct': 'UserDefUnionBase',
'base': 'UserDefZero',
'data': { 'string': 'str', 'enum1': 'EnumOne' } }
{ 'struct': 'UserDefZero',
'data': { 'integer': 'int' } }
Patch's effect on UserDefFlatUnion:
struct UserDefFlatUnion {
/* Members inherited from UserDefUnionBase: */
+ int64_t integer;
char *string;
EnumOne enum1;
/* Own members: */
union { /* union tag is @enum1 */
void *data;
UserDefA *value1;
UserDefB *value2;
UserDefB *value3;
};
};
Flat union visitors remain broken. They'll be fixed next.
Code is generated in a different order now, but that doesn't matter.
The two guards QAPI_TYPES_BUILTIN_STRUCT_DECL and
QAPI_TYPES_BUILTIN_CLEANUP_DECL are replaced by just
QAPI_TYPES_BUILTIN.
Two ugly special cases for simple unions now stand out like sore
thumbs:
1. The type tag is named 'type' everywhere, except in generated C,
where it's 'kind'.
2. QAPISchema lowers simple unions to semantically equivalent flat
unions. However, the C generated for a simple unions differs from
the C generated for its equivalent flat union, and we therefore
need special code to preserve that pointless difference for now.
Mark both TODO.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
2015-09-16 13:06:09 +02:00
|
|
|
|
|
|
|
for var in variants.variants:
|
2018-06-18 10:40:05 +02:00
|
|
|
if var.type.name == 'q_empty':
|
|
|
|
continue
|
2021-08-31 14:37:58 +02:00
|
|
|
ret += var.ifcond.gen_if()
|
qapi: Finish converting to new qapi union layout
We have two issues with our qapi union layout:
1) Even though the QMP wire format spells the tag 'type', the
C code spells it 'kind', requiring some hacks in the generator.
2) The C struct uses an anonymous union, which places all tag
values in the same namespace as all non-variant members. This
leads to spurious collisions if a tag value matches a non-variant
member's name.
This patch is the back end for a series that converts to a
saner qapi union layout. Now that all clients have been
converted to use 'type' and 'obj->u.value', we can drop the
temporary parallel support for 'kind' and 'obj->value'.
Given a simple union qapi type:
{ 'union':'Foo', 'data': { 'a':'int', 'b':'bool' } }
this is the overall effect, when compared to the state before
this series of patches:
| struct Foo {
|- FooKind kind;
|- union { /* union tag is @kind */
|+ FooKind type;
|+ union { /* union tag is @type */
| void *data;
| int64_t a;
| bool b;
|- };
|+ } u;
| };
The testsuite still contains some examples of artificial restrictions
(see flat-union-clash-type.json, for example) that are no longer
technically necessary, now that there is no longer a collision between
enum tag values and non-variant member names; but fixing this will be
done in later patches, in part because some further changes are required
to keep QAPISchema*.check() from asserting. Also, a later patch will
add a reservation for the member name 'u' to avoid a collision between a
user's non-variant names and our internal choice of C union name.
Note, however, that we do not rename the generated enum, which
is still 'FooKind'. A further patch could generate implicit
enums as 'FooType', but while the generator already reserved
the '*Kind' namespace (commit 4dc2e69), there are already QMP
constructs with '*Type' naming, which means changing our
reservation namespace would have lots of churn to C code to
deal with a forced name change.
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1445898903-12082-23-git-send-email-eblake@redhat.com>
[Commit message tweaked]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2015-10-26 23:35:01 +01:00
|
|
|
ret += mcgen('''
|
2011-07-19 21:50:40 +02:00
|
|
|
%(c_type)s %(c_name)s;
|
|
|
|
''',
|
qapi: Don't special-case simple union wrappers
Simple unions were carrying a special case that hid their 'data'
QMP member from the resulting C struct, via the hack method
QAPISchemaObjectTypeVariant.simple_union_type(). But by using
the work we started by unboxing flat union and alternate
branches, coupled with the ability to visit the members of an
implicit type, we can now expose the simple union's implicit
type in qapi-types.h:
| struct q_obj_ImageInfoSpecificQCow2_wrapper {
| ImageInfoSpecificQCow2 *data;
| };
|
| struct q_obj_ImageInfoSpecificVmdk_wrapper {
| ImageInfoSpecificVmdk *data;
| };
...
| struct ImageInfoSpecific {
| ImageInfoSpecificKind type;
| union { /* union tag is @type */
| void *data;
|- ImageInfoSpecificQCow2 *qcow2;
|- ImageInfoSpecificVmdk *vmdk;
|+ q_obj_ImageInfoSpecificQCow2_wrapper qcow2;
|+ q_obj_ImageInfoSpecificVmdk_wrapper vmdk;
| } u;
| };
Doing this removes asymmetry between QAPI's QMP side and its
C side (both sides now expose 'data'), and means that the
treatment of a simple union as sugar for a flat union is now
equivalent in both languages (previously the two approaches used
a different layer of dereferencing, where the simple union could
be converted to a flat union with equivalent C layout but
different {} on the wire, or to an equivalent QMP wire form
but with different C representation). Using the implicit type
also lets us get rid of the simple_union_type() hack.
Of course, now all clients of simple unions have to adjust from
using su->u.member to using su->u.member.data; while this touches
a number of files in the tree, some earlier cleanup patches
helped minimize the change to the initialization of a temporary
variable rather than every single member access. The generated
qapi-visit.c code is also affected by the layout change:
|@@ -7393,10 +7393,10 @@ void visit_type_ImageInfoSpecific_member
| }
| switch (obj->type) {
| case IMAGE_INFO_SPECIFIC_KIND_QCOW2:
|- visit_type_ImageInfoSpecificQCow2(v, "data", &obj->u.qcow2, &err);
|+ visit_type_q_obj_ImageInfoSpecificQCow2_wrapper_members(v, &obj->u.qcow2, &err);
| break;
| case IMAGE_INFO_SPECIFIC_KIND_VMDK:
|- visit_type_ImageInfoSpecificVmdk(v, "data", &obj->u.vmdk, &err);
|+ visit_type_q_obj_ImageInfoSpecificVmdk_wrapper_members(v, &obj->u.vmdk, &err);
| break;
| default:
| abort();
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1458254921-17042-13-git-send-email-eblake@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-03-17 23:48:37 +01:00
|
|
|
c_type=var.type.c_unboxed_type(),
|
qapi-types: Convert to QAPISchemaVisitor, fixing flat unions
Fixes flat unions to get the base's base members. Test case is from
commit 2fc0043, in qapi-schema-test.json:
{ 'union': 'UserDefFlatUnion',
'base': 'UserDefUnionBase',
'discriminator': 'enum1',
'data': { 'value1' : 'UserDefA',
'value2' : 'UserDefB',
'value3' : 'UserDefB' } }
{ 'struct': 'UserDefUnionBase',
'base': 'UserDefZero',
'data': { 'string': 'str', 'enum1': 'EnumOne' } }
{ 'struct': 'UserDefZero',
'data': { 'integer': 'int' } }
Patch's effect on UserDefFlatUnion:
struct UserDefFlatUnion {
/* Members inherited from UserDefUnionBase: */
+ int64_t integer;
char *string;
EnumOne enum1;
/* Own members: */
union { /* union tag is @enum1 */
void *data;
UserDefA *value1;
UserDefB *value2;
UserDefB *value3;
};
};
Flat union visitors remain broken. They'll be fixed next.
Code is generated in a different order now, but that doesn't matter.
The two guards QAPI_TYPES_BUILTIN_STRUCT_DECL and
QAPI_TYPES_BUILTIN_CLEANUP_DECL are replaced by just
QAPI_TYPES_BUILTIN.
Two ugly special cases for simple unions now stand out like sore
thumbs:
1. The type tag is named 'type' everywhere, except in generated C,
where it's 'kind'.
2. QAPISchema lowers simple unions to semantically equivalent flat
unions. However, the C generated for a simple unions differs from
the C generated for its equivalent flat union, and we therefore
need special code to preserve that pointless difference for now.
Mark both TODO.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
2015-09-16 13:06:09 +02:00
|
|
|
c_name=c_name(var.name))
|
2021-08-31 14:37:58 +02:00
|
|
|
ret += var.ifcond.gen_endif()
|
2011-07-19 21:50:40 +02:00
|
|
|
|
|
|
|
ret += mcgen('''
|
qapi: Start converting to new qapi union layout
We have two issues with our qapi union layout:
1) Even though the QMP wire format spells the tag 'type', the
C code spells it 'kind', requiring some hacks in the generator.
2) The C struct uses an anonymous union, which places all tag
values in the same namespace as all non-variant members. This
leads to spurious collisions if a tag value matches a non-variant
member's name.
This patch is the front end for a series that converts to a
saner qapi union layout. By the end of the series, we will no
longer have the type/kind mismatch, and all tag values will be
under a named union, which requires clients to access
'obj->u.value' instead of 'obj->value'. But since the
conversion touches a number of files, it is easiest if we
temporarily support BOTH layouts simultaneously.
Given a simple union qapi type:
{ 'union':'Foo', 'data': { 'a':'int', 'b':'bool' } }
make the following changes in generated qapi-types.h:
| struct Foo {
|- FooKind kind;
|- union { /* union tag is @kind */
|+ union {
|+ FooKind kind;
|+ FooKind type;
|+ };
|+ union { /* union tag is @type */
| void *data;
| int64_t a;
| bool b;
|+ union { /* union tag is @type */
|+ void *data;
|+ int64_t a;
|+ bool b;
|+ } u;
| };
| };
Flat unions do not need the anonymous union for the tag member,
as we already fixed that to use the member name instead of 'kind'
back in commit 0f61af3e.
One additional change is needed in qapi.py: check_union() now
needs to check for collisions with 'type' in addition to those
with 'kind'.
Later, when the conversions are complete, we will remove the
duplication hacks, and also drop the check_union() restrictions.
Note, however, that we do not rename the generated enum, which
is still 'FooKind'. A further patch could generate implicit
enums as 'FooType', but while the generator already reserved
the '*Kind' namespace (commit 4dc2e69), there are already QMP
constructs with '*Type' naming, which means changing our
reservation namespace would have lots of churn to C code to
deal with a forced name change.
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1445898903-12082-13-git-send-email-eblake@redhat.com>
[Commit message tweaked slightly]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2015-10-26 23:34:51 +01:00
|
|
|
} u;
|
2011-07-19 21:50:40 +02:00
|
|
|
''')
|
|
|
|
|
|
|
|
return ret
|
|
|
|
|
2015-09-16 13:06:16 +02:00
|
|
|
|
2020-10-09 18:15:54 +02:00
|
|
|
def gen_type_cleanup_decl(name: str) -> str:
|
2011-07-19 21:50:40 +02:00
|
|
|
ret = mcgen('''
|
qapi-types: Convert to QAPISchemaVisitor, fixing flat unions
Fixes flat unions to get the base's base members. Test case is from
commit 2fc0043, in qapi-schema-test.json:
{ 'union': 'UserDefFlatUnion',
'base': 'UserDefUnionBase',
'discriminator': 'enum1',
'data': { 'value1' : 'UserDefA',
'value2' : 'UserDefB',
'value3' : 'UserDefB' } }
{ 'struct': 'UserDefUnionBase',
'base': 'UserDefZero',
'data': { 'string': 'str', 'enum1': 'EnumOne' } }
{ 'struct': 'UserDefZero',
'data': { 'integer': 'int' } }
Patch's effect on UserDefFlatUnion:
struct UserDefFlatUnion {
/* Members inherited from UserDefUnionBase: */
+ int64_t integer;
char *string;
EnumOne enum1;
/* Own members: */
union { /* union tag is @enum1 */
void *data;
UserDefA *value1;
UserDefB *value2;
UserDefB *value3;
};
};
Flat union visitors remain broken. They'll be fixed next.
Code is generated in a different order now, but that doesn't matter.
The two guards QAPI_TYPES_BUILTIN_STRUCT_DECL and
QAPI_TYPES_BUILTIN_CLEANUP_DECL are replaced by just
QAPI_TYPES_BUILTIN.
Two ugly special cases for simple unions now stand out like sore
thumbs:
1. The type tag is named 'type' everywhere, except in generated C,
where it's 'kind'.
2. QAPISchema lowers simple unions to semantically equivalent flat
unions. However, the C generated for a simple unions differs from
the C generated for its equivalent flat union, and we therefore
need special code to preserve that pointless difference for now.
Mark both TODO.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
2015-09-16 13:06:09 +02:00
|
|
|
|
2015-09-16 13:06:16 +02:00
|
|
|
void qapi_free_%(c_name)s(%(c_name)s *obj);
|
qapi: enable use of g_autoptr with QAPI types
Currently QAPI generates a type and function for free'ing it:
typedef struct QCryptoBlockCreateOptions QCryptoBlockCreateOptions;
void qapi_free_QCryptoBlockCreateOptions(QCryptoBlockCreateOptions *obj);
This is used in the traditional manner:
QCryptoBlockCreateOptions *opts = NULL;
opts = g_new0(QCryptoBlockCreateOptions, 1);
....do stuff with opts...
qapi_free_QCryptoBlockCreateOptions(opts);
Since bumping the min glib to 2.48, QEMU has incrementally adopted the
use of g_auto/g_autoptr. This allows the compiler to run a function to
free a variable when it goes out of scope, the benefit being the
compiler can guarantee it is freed in all possible code ptahs.
This benefit is applicable to QAPI types too, and given the seriously
long method names for some qapi_free_XXXX() functions, is much less
typing. This change thus makes the code generator emit:
G_DEFINE_AUTOPTR_CLEANUP_FUNC(QCryptoBlockCreateOptions,
qapi_free_QCryptoBlockCreateOptions)
The above code example now becomes
g_autoptr(QCryptoBlockCreateOptions) opts = NULL;
opts = g_new0(QCryptoBlockCreateOptions, 1);
....do stuff with opts...
Note, if the local pointer needs to live beyond the scope holding the
variable, then g_steal_pointer can be used. This is useful to return the
pointer to the caller in the success codepath, while letting it be freed
in all error codepaths.
return g_steal_pointer(&opts);
The crypto/block.h header needs updating to avoid symbol clash now that
the g_autoptr support is a standard QAPI feature.
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
Message-Id: <20200723153845.2934357-1-berrange@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2020-07-23 17:38:45 +02:00
|
|
|
G_DEFINE_AUTOPTR_CLEANUP_FUNC(%(c_name)s, qapi_free_%(c_name)s)
|
2011-07-19 21:50:40 +02:00
|
|
|
''',
|
2015-09-16 13:06:16 +02:00
|
|
|
c_name=c_name(name))
|
2011-07-19 21:50:40 +02:00
|
|
|
return ret
|
|
|
|
|
2015-09-16 13:06:16 +02:00
|
|
|
|
2020-10-09 18:15:54 +02:00
|
|
|
def gen_type_cleanup(name: str) -> str:
|
2011-07-19 21:50:40 +02:00
|
|
|
ret = mcgen('''
|
2013-05-11 00:46:00 +02:00
|
|
|
|
2015-09-16 13:06:16 +02:00
|
|
|
void qapi_free_%(c_name)s(%(c_name)s *obj)
|
2011-07-19 21:50:40 +02:00
|
|
|
{
|
|
|
|
Visitor *v;
|
|
|
|
|
|
|
|
if (!obj) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
qapi: Add new visit_free() function
Making each visitor provide its own (awkwardly-named) FOO_cleanup()
is unusual, when we can instead have a polymorphic visit_free()
interface. Over the next few patches, we can use the polymorphic
functions to eliminate the need for a FOO_get_visitor() function
for accessing specific visitor functionality, once everything can
be accessed directly through the Visitor* interfaces.
The dealloc visitor is the first one converted to completely use
the new entry point, since qapi_dealloc_visitor_cleanup() was the
only reason that qapi_dealloc_get_visitor() existed, and only
generated and testsuite code was even using it. With the new
visit_free() entry point in place, we no longer need to expose
the QapiDeallocVisitor subtype through qapi_dealloc_visitor_new(),
and can get by with less generated code, with diffs that look like:
| void qapi_free_ACPIOSTInfo(ACPIOSTInfo *obj)
| {
|- QapiDeallocVisitor *qdv;
| Visitor *v;
|
| if (!obj) {
| return;
| }
|
|- qdv = qapi_dealloc_visitor_new();
|- v = qapi_dealloc_get_visitor(qdv);
|+ v = qapi_dealloc_visitor_new();
| visit_type_ACPIOSTInfo(v, NULL, &obj, NULL);
|- qapi_dealloc_visitor_cleanup(qdv);
|+ visit_free(v);
|}
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1465490926-28625-5-git-send-email-eblake@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-06-09 18:48:35 +02:00
|
|
|
v = qapi_dealloc_visitor_new();
|
qapi: Swap visit_* arguments for consistent 'name' placement
JSON uses "name":value, but many of our visitor interfaces were
called with visit_type_FOO(v, &value, name, errp). This can be
a bit confusing to have to mentally swap the parameter order to
match JSON order. It's particularly bad for visit_start_struct(),
where the 'name' parameter is smack in the middle of the
otherwise-related group of 'obj, kind, size' parameters! It's
time to do a global swap of the parameter ordering, so that the
'name' parameter is always immediately after the Visitor argument.
Additional reason in favor of the swap: the existing include/qjson.h
prefers listing 'name' first in json_prop_*(), and I have plans to
unify that file with the qapi visitors; listing 'name' first in
qapi will minimize churn to the (admittedly few) qjson.h clients.
Later patches will then fix docs, object.h, visitor-impl.h, and
those clients to match.
Done by first patching scripts/qapi*.py by hand to make generated
files do what I want, then by running the following Coccinelle
script to affect the rest of the code base:
$ spatch --sp-file script `git grep -l '\bvisit_' -- '**/*.[ch]'`
I then had to apply some touchups (Coccinelle insisted on TAB
indentation in visitor.h, and botched the signature of
visit_type_enum() by rewriting 'const char *const strings[]' to
the syntactically invalid 'const char*const[] strings'). The
movement of parameters is sufficient to provoke compiler errors
if any callers were missed.
// Part 1: Swap declaration order
@@
type TV, TErr, TObj, T1, T2;
identifier OBJ, ARG1, ARG2;
@@
void visit_start_struct
-(TV v, TObj OBJ, T1 ARG1, const char *name, T2 ARG2, TErr errp)
+(TV v, const char *name, TObj OBJ, T1 ARG1, T2 ARG2, TErr errp)
{ ... }
@@
type bool, TV, T1;
identifier ARG1;
@@
bool visit_optional
-(TV v, T1 ARG1, const char *name)
+(TV v, const char *name, T1 ARG1)
{ ... }
@@
type TV, TErr, TObj, T1;
identifier OBJ, ARG1;
@@
void visit_get_next_type
-(TV v, TObj OBJ, T1 ARG1, const char *name, TErr errp)
+(TV v, const char *name, TObj OBJ, T1 ARG1, TErr errp)
{ ... }
@@
type TV, TErr, TObj, T1, T2;
identifier OBJ, ARG1, ARG2;
@@
void visit_type_enum
-(TV v, TObj OBJ, T1 ARG1, T2 ARG2, const char *name, TErr errp)
+(TV v, const char *name, TObj OBJ, T1 ARG1, T2 ARG2, TErr errp)
{ ... }
@@
type TV, TErr, TObj;
identifier OBJ;
identifier VISIT_TYPE =~ "^visit_type_";
@@
void VISIT_TYPE
-(TV v, TObj OBJ, const char *name, TErr errp)
+(TV v, const char *name, TObj OBJ, TErr errp)
{ ... }
// Part 2: swap caller order
@@
expression V, NAME, OBJ, ARG1, ARG2, ERR;
identifier VISIT_TYPE =~ "^visit_type_";
@@
(
-visit_start_struct(V, OBJ, ARG1, NAME, ARG2, ERR)
+visit_start_struct(V, NAME, OBJ, ARG1, ARG2, ERR)
|
-visit_optional(V, ARG1, NAME)
+visit_optional(V, NAME, ARG1)
|
-visit_get_next_type(V, OBJ, ARG1, NAME, ERR)
+visit_get_next_type(V, NAME, OBJ, ARG1, ERR)
|
-visit_type_enum(V, OBJ, ARG1, ARG2, NAME, ERR)
+visit_type_enum(V, NAME, OBJ, ARG1, ARG2, ERR)
|
-VISIT_TYPE(V, OBJ, NAME, ERR)
+VISIT_TYPE(V, NAME, OBJ, ERR)
)
Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <1454075341-13658-19-git-send-email-eblake@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-01-29 14:48:54 +01:00
|
|
|
visit_type_%(c_name)s(v, NULL, &obj, NULL);
|
qapi: Add new visit_free() function
Making each visitor provide its own (awkwardly-named) FOO_cleanup()
is unusual, when we can instead have a polymorphic visit_free()
interface. Over the next few patches, we can use the polymorphic
functions to eliminate the need for a FOO_get_visitor() function
for accessing specific visitor functionality, once everything can
be accessed directly through the Visitor* interfaces.
The dealloc visitor is the first one converted to completely use
the new entry point, since qapi_dealloc_visitor_cleanup() was the
only reason that qapi_dealloc_get_visitor() existed, and only
generated and testsuite code was even using it. With the new
visit_free() entry point in place, we no longer need to expose
the QapiDeallocVisitor subtype through qapi_dealloc_visitor_new(),
and can get by with less generated code, with diffs that look like:
| void qapi_free_ACPIOSTInfo(ACPIOSTInfo *obj)
| {
|- QapiDeallocVisitor *qdv;
| Visitor *v;
|
| if (!obj) {
| return;
| }
|
|- qdv = qapi_dealloc_visitor_new();
|- v = qapi_dealloc_get_visitor(qdv);
|+ v = qapi_dealloc_visitor_new();
| visit_type_ACPIOSTInfo(v, NULL, &obj, NULL);
|- qapi_dealloc_visitor_cleanup(qdv);
|+ visit_free(v);
|}
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1465490926-28625-5-git-send-email-eblake@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-06-09 18:48:35 +02:00
|
|
|
visit_free(v);
|
2011-07-19 21:50:40 +02:00
|
|
|
}
|
|
|
|
''',
|
2015-09-16 13:06:16 +02:00
|
|
|
c_name=c_name(name))
|
2011-07-19 21:50:40 +02:00
|
|
|
return ret
|
|
|
|
|
qapi-types: Convert to QAPISchemaVisitor, fixing flat unions
Fixes flat unions to get the base's base members. Test case is from
commit 2fc0043, in qapi-schema-test.json:
{ 'union': 'UserDefFlatUnion',
'base': 'UserDefUnionBase',
'discriminator': 'enum1',
'data': { 'value1' : 'UserDefA',
'value2' : 'UserDefB',
'value3' : 'UserDefB' } }
{ 'struct': 'UserDefUnionBase',
'base': 'UserDefZero',
'data': { 'string': 'str', 'enum1': 'EnumOne' } }
{ 'struct': 'UserDefZero',
'data': { 'integer': 'int' } }
Patch's effect on UserDefFlatUnion:
struct UserDefFlatUnion {
/* Members inherited from UserDefUnionBase: */
+ int64_t integer;
char *string;
EnumOne enum1;
/* Own members: */
union { /* union tag is @enum1 */
void *data;
UserDefA *value1;
UserDefB *value2;
UserDefB *value3;
};
};
Flat union visitors remain broken. They'll be fixed next.
Code is generated in a different order now, but that doesn't matter.
The two guards QAPI_TYPES_BUILTIN_STRUCT_DECL and
QAPI_TYPES_BUILTIN_CLEANUP_DECL are replaced by just
QAPI_TYPES_BUILTIN.
Two ugly special cases for simple unions now stand out like sore
thumbs:
1. The type tag is named 'type' everywhere, except in generated C,
where it's 'kind'.
2. QAPISchema lowers simple unions to semantically equivalent flat
unions. However, the C generated for a simple unions differs from
the C generated for its equivalent flat union, and we therefore
need special code to preserve that pointless difference for now.
Mark both TODO.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
2015-09-16 13:06:09 +02:00
|
|
|
|
qapi/types qapi/visit: Generate built-in stuff into separate files
Linking code from multiple separate QAPI schemata into the same
program is possible, but involves some weirdness around built-in
types:
* We generate code for built-in types into .c only with option
--builtins. The user is responsible for generating code for exactly
one QAPI schema per program with --builtins.
* We generate code for built-in types into .h regardless of
--builtins, but guarded by #ifndef QAPI_VISIT_BUILTIN. Because all
copies of this code are exactly the same, including any combination
of these headers works.
Replace this contraption by something more conventional: generate code
for built-in types into their very own files: qapi-builtin-types.c,
qapi-builtin-visit.c, qapi-builtin-types.h, qapi-builtin-visit.h, but
only with --builtins. Obey --output-dir, but ignore --prefix for
them.
Make qapi-types.h include qapi-builtin-types.h. With multiple
schemata you now have multiple qapi-types.[ch], but only one
qapi-builtin-types.[ch]. Same for qapi-visit.[ch] and
qapi-builtin-visit.[ch].
Bonus: if all you need is built-in stuff, you can include a much
smaller header. To be exploited shortly.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Message-Id: <20180211093607.27351-21-armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Michael Roth <mdroth@linux.vnet.ibm.com>
[eblake: fix octal constant for python 3]
Signed-off-by: Eric Blake <eblake@redhat.com>
2018-02-26 23:29:21 +01:00
|
|
|
class QAPISchemaGenTypeVisitor(QAPISchemaModularCVisitor):
|
2018-02-26 20:50:08 +01:00
|
|
|
|
2020-10-09 18:15:54 +02:00
|
|
|
def __init__(self, prefix: str):
|
2020-03-04 16:59:31 +01:00
|
|
|
super().__init__(
|
|
|
|
prefix, 'qapi-types', ' * Schema-defined QAPI types',
|
2019-11-20 19:25:51 +01:00
|
|
|
' * Built-in QAPI types', __doc__)
|
|
|
|
|
2021-02-01 20:37:37 +01:00
|
|
|
def _begin_builtin_module(self) -> None:
|
qapi/types qapi/visit: Generate built-in stuff into separate files
Linking code from multiple separate QAPI schemata into the same
program is possible, but involves some weirdness around built-in
types:
* We generate code for built-in types into .c only with option
--builtins. The user is responsible for generating code for exactly
one QAPI schema per program with --builtins.
* We generate code for built-in types into .h regardless of
--builtins, but guarded by #ifndef QAPI_VISIT_BUILTIN. Because all
copies of this code are exactly the same, including any combination
of these headers works.
Replace this contraption by something more conventional: generate code
for built-in types into their very own files: qapi-builtin-types.c,
qapi-builtin-visit.c, qapi-builtin-types.h, qapi-builtin-visit.h, but
only with --builtins. Obey --output-dir, but ignore --prefix for
them.
Make qapi-types.h include qapi-builtin-types.h. With multiple
schemata you now have multiple qapi-types.[ch], but only one
qapi-builtin-types.[ch]. Same for qapi-visit.[ch] and
qapi-builtin-visit.[ch].
Bonus: if all you need is built-in stuff, you can include a much
smaller header. To be exploited shortly.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Message-Id: <20180211093607.27351-21-armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Michael Roth <mdroth@linux.vnet.ibm.com>
[eblake: fix octal constant for python 3]
Signed-off-by: Eric Blake <eblake@redhat.com>
2018-02-26 23:29:21 +01:00
|
|
|
self._genc.preamble_add(mcgen('''
|
|
|
|
#include "qemu/osdep.h"
|
|
|
|
#include "qapi/dealloc-visitor.h"
|
2018-02-11 10:36:05 +01:00
|
|
|
#include "qapi/qapi-builtin-types.h"
|
|
|
|
#include "qapi/qapi-builtin-visit.h"
|
qapi/types qapi/visit: Generate built-in stuff into separate files
Linking code from multiple separate QAPI schemata into the same
program is possible, but involves some weirdness around built-in
types:
* We generate code for built-in types into .c only with option
--builtins. The user is responsible for generating code for exactly
one QAPI schema per program with --builtins.
* We generate code for built-in types into .h regardless of
--builtins, but guarded by #ifndef QAPI_VISIT_BUILTIN. Because all
copies of this code are exactly the same, including any combination
of these headers works.
Replace this contraption by something more conventional: generate code
for built-in types into their very own files: qapi-builtin-types.c,
qapi-builtin-visit.c, qapi-builtin-types.h, qapi-builtin-visit.h, but
only with --builtins. Obey --output-dir, but ignore --prefix for
them.
Make qapi-types.h include qapi-builtin-types.h. With multiple
schemata you now have multiple qapi-types.[ch], but only one
qapi-builtin-types.[ch]. Same for qapi-visit.[ch] and
qapi-builtin-visit.[ch].
Bonus: if all you need is built-in stuff, you can include a much
smaller header. To be exploited shortly.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Message-Id: <20180211093607.27351-21-armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Michael Roth <mdroth@linux.vnet.ibm.com>
[eblake: fix octal constant for python 3]
Signed-off-by: Eric Blake <eblake@redhat.com>
2018-02-26 23:29:21 +01:00
|
|
|
'''))
|
|
|
|
self._genh.preamble_add(mcgen('''
|
|
|
|
#include "qapi/util.h"
|
|
|
|
'''))
|
|
|
|
|
2020-10-09 18:15:54 +02:00
|
|
|
def _begin_user_module(self, name: str) -> None:
|
2018-02-11 10:36:01 +01:00
|
|
|
types = self._module_basename('qapi-types', name)
|
|
|
|
visit = self._module_basename('qapi-visit', name)
|
2018-02-26 20:50:08 +01:00
|
|
|
self._genc.preamble_add(mcgen('''
|
|
|
|
#include "qemu/osdep.h"
|
|
|
|
#include "qapi/dealloc-visitor.h"
|
2018-02-11 10:36:01 +01:00
|
|
|
#include "%(types)s.h"
|
|
|
|
#include "%(visit)s.h"
|
2018-02-26 20:50:08 +01:00
|
|
|
''',
|
2018-02-11 10:36:01 +01:00
|
|
|
types=types, visit=visit))
|
2018-02-26 20:50:08 +01:00
|
|
|
self._genh.preamble_add(mcgen('''
|
2018-02-11 10:36:05 +01:00
|
|
|
#include "qapi/qapi-builtin-types.h"
|
2018-02-26 20:50:08 +01:00
|
|
|
'''))
|
qapi-types: Convert to QAPISchemaVisitor, fixing flat unions
Fixes flat unions to get the base's base members. Test case is from
commit 2fc0043, in qapi-schema-test.json:
{ 'union': 'UserDefFlatUnion',
'base': 'UserDefUnionBase',
'discriminator': 'enum1',
'data': { 'value1' : 'UserDefA',
'value2' : 'UserDefB',
'value3' : 'UserDefB' } }
{ 'struct': 'UserDefUnionBase',
'base': 'UserDefZero',
'data': { 'string': 'str', 'enum1': 'EnumOne' } }
{ 'struct': 'UserDefZero',
'data': { 'integer': 'int' } }
Patch's effect on UserDefFlatUnion:
struct UserDefFlatUnion {
/* Members inherited from UserDefUnionBase: */
+ int64_t integer;
char *string;
EnumOne enum1;
/* Own members: */
union { /* union tag is @enum1 */
void *data;
UserDefA *value1;
UserDefB *value2;
UserDefB *value3;
};
};
Flat union visitors remain broken. They'll be fixed next.
Code is generated in a different order now, but that doesn't matter.
The two guards QAPI_TYPES_BUILTIN_STRUCT_DECL and
QAPI_TYPES_BUILTIN_CLEANUP_DECL are replaced by just
QAPI_TYPES_BUILTIN.
Two ugly special cases for simple unions now stand out like sore
thumbs:
1. The type tag is named 'type' everywhere, except in generated C,
where it's 'kind'.
2. QAPISchema lowers simple unions to semantically equivalent flat
unions. However, the C generated for a simple unions differs from
the C generated for its equivalent flat union, and we therefore
need special code to preserve that pointless difference for now.
Mark both TODO.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
2015-09-16 13:06:09 +02:00
|
|
|
|
2020-10-09 18:15:54 +02:00
|
|
|
def visit_begin(self, schema: QAPISchema) -> None:
|
qapi: Emit implicit structs in generated C
We already have several places that want to visit all the members
of an implicit object within a larger context (simple union variant,
event with anonymous data, command with anonymous arguments struct);
and will be adding another one soon (the ability to declare an
anonymous base for a flat union). Having a C struct declared for
these implicit types, along with a visit_type_FOO_members() helper
function, will make for fewer special cases in our generator.
We do not, however, need qapi_free_FOO() or visit_type_FOO()
functions for implicit types, because they should not be used
directly outside of the generated code. This is done by adding a
conditional in visit_object_type() for both qapi-types.py and
qapi-visit.py based on the object name. The comparison of
"name.startswith('q_')" is a bit hacky (it's basically duplicating
what .is_implicit() already uses), but beats changing the signature
of the visit_object_type() callback to pass a new 'implicit' flag.
The hack should be temporary: we are considering adding a future
patch that consolidates the narrow visit_object_type(..., base,
local_members, variants) and visit_object_type_flat(...,
all_members, variants) [where different sets of information are
already broken out, and the QAPISchemaObjectType is no longer
available] into a broader visit_object_type(obj_type) [where the
visitor can query the needed fields from obj_type directly].
Also, now that we WANT to output C code for implicits, we no longer
need the visit_needed() filter, leaving 'q_empty' as the only object
still needing a special case. Remember, 'q_empty' is the only
built-in generated object, which means that without a special case
it would be emitted in multiple files (the main qapi-types.h and in
qga-qapi-types.h) causing compilation failure due to redefinition.
But since it has no members, it's easier to just avoid an attempt to
visit that particular type; since gen_object() is called recursively,
we also prime the objects_seen set to cover any recursion into the
empty type.
The patch relies on the changed naming of implicit types in the
previous patch. It is a bit unfortunate that the generated struct
names and visit_type_FOO_members() don't match normal naming
conventions, but it's not too bad, since they will only be used in
generated code.
The generated code grows substantially in size: the implicit
'-wrapper' types must be emitted in qapi-types.h before any union
can include an unboxed member of that type. Arguably, the '-args'
types could be emitted in a private header for just qapi-visit.c
and qmp-marshal.c, rather than polluting qapi-types.h; but adding
complexity to the generator to split the output location according
to role doesn't seem worth the maintenance costs.
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1458254921-17042-6-git-send-email-eblake@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-03-17 23:48:30 +01:00
|
|
|
# gen_object() is recursive, ensure it doesn't visit the empty type
|
|
|
|
objects_seen.add(schema.the_empty_object_type.name)
|
qapi-types: Convert to QAPISchemaVisitor, fixing flat unions
Fixes flat unions to get the base's base members. Test case is from
commit 2fc0043, in qapi-schema-test.json:
{ 'union': 'UserDefFlatUnion',
'base': 'UserDefUnionBase',
'discriminator': 'enum1',
'data': { 'value1' : 'UserDefA',
'value2' : 'UserDefB',
'value3' : 'UserDefB' } }
{ 'struct': 'UserDefUnionBase',
'base': 'UserDefZero',
'data': { 'string': 'str', 'enum1': 'EnumOne' } }
{ 'struct': 'UserDefZero',
'data': { 'integer': 'int' } }
Patch's effect on UserDefFlatUnion:
struct UserDefFlatUnion {
/* Members inherited from UserDefUnionBase: */
+ int64_t integer;
char *string;
EnumOne enum1;
/* Own members: */
union { /* union tag is @enum1 */
void *data;
UserDefA *value1;
UserDefB *value2;
UserDefB *value3;
};
};
Flat union visitors remain broken. They'll be fixed next.
Code is generated in a different order now, but that doesn't matter.
The two guards QAPI_TYPES_BUILTIN_STRUCT_DECL and
QAPI_TYPES_BUILTIN_CLEANUP_DECL are replaced by just
QAPI_TYPES_BUILTIN.
Two ugly special cases for simple unions now stand out like sore
thumbs:
1. The type tag is named 'type' everywhere, except in generated C,
where it's 'kind'.
2. QAPISchema lowers simple unions to semantically equivalent flat
unions. However, the C generated for a simple unions differs from
the C generated for its equivalent flat union, and we therefore
need special code to preserve that pointless difference for now.
Mark both TODO.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
2015-09-16 13:06:09 +02:00
|
|
|
|
2020-10-09 18:15:54 +02:00
|
|
|
def _gen_type_cleanup(self, name: str) -> None:
|
2018-02-26 20:50:08 +01:00
|
|
|
self._genh.add(gen_type_cleanup_decl(name))
|
|
|
|
self._genc.add(gen_type_cleanup(name))
|
qapi-types: Convert to QAPISchemaVisitor, fixing flat unions
Fixes flat unions to get the base's base members. Test case is from
commit 2fc0043, in qapi-schema-test.json:
{ 'union': 'UserDefFlatUnion',
'base': 'UserDefUnionBase',
'discriminator': 'enum1',
'data': { 'value1' : 'UserDefA',
'value2' : 'UserDefB',
'value3' : 'UserDefB' } }
{ 'struct': 'UserDefUnionBase',
'base': 'UserDefZero',
'data': { 'string': 'str', 'enum1': 'EnumOne' } }
{ 'struct': 'UserDefZero',
'data': { 'integer': 'int' } }
Patch's effect on UserDefFlatUnion:
struct UserDefFlatUnion {
/* Members inherited from UserDefUnionBase: */
+ int64_t integer;
char *string;
EnumOne enum1;
/* Own members: */
union { /* union tag is @enum1 */
void *data;
UserDefA *value1;
UserDefB *value2;
UserDefB *value3;
};
};
Flat union visitors remain broken. They'll be fixed next.
Code is generated in a different order now, but that doesn't matter.
The two guards QAPI_TYPES_BUILTIN_STRUCT_DECL and
QAPI_TYPES_BUILTIN_CLEANUP_DECL are replaced by just
QAPI_TYPES_BUILTIN.
Two ugly special cases for simple unions now stand out like sore
thumbs:
1. The type tag is named 'type' everywhere, except in generated C,
where it's 'kind'.
2. QAPISchema lowers simple unions to semantically equivalent flat
unions. However, the C generated for a simple unions differs from
the C generated for its equivalent flat union, and we therefore
need special code to preserve that pointless difference for now.
Mark both TODO.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
2015-09-16 13:06:09 +02:00
|
|
|
|
2020-10-09 18:15:54 +02:00
|
|
|
def visit_enum_type(self,
|
|
|
|
name: str,
|
|
|
|
info: Optional[QAPISourceInfo],
|
2021-08-04 10:30:57 +02:00
|
|
|
ifcond: QAPISchemaIfCond,
|
2020-10-09 18:15:54 +02:00
|
|
|
features: List[QAPISchemaFeature],
|
|
|
|
members: List[QAPISchemaEnumMember],
|
|
|
|
prefix: Optional[str]) -> None:
|
2018-07-03 17:56:45 +02:00
|
|
|
with ifcontext(ifcond, self._genh, self._genc):
|
2018-12-13 13:37:04 +01:00
|
|
|
self._genh.preamble_add(gen_enum(name, members, prefix))
|
|
|
|
self._genc.add(gen_enum_lookup(name, members, prefix))
|
qapi-types: Convert to QAPISchemaVisitor, fixing flat unions
Fixes flat unions to get the base's base members. Test case is from
commit 2fc0043, in qapi-schema-test.json:
{ 'union': 'UserDefFlatUnion',
'base': 'UserDefUnionBase',
'discriminator': 'enum1',
'data': { 'value1' : 'UserDefA',
'value2' : 'UserDefB',
'value3' : 'UserDefB' } }
{ 'struct': 'UserDefUnionBase',
'base': 'UserDefZero',
'data': { 'string': 'str', 'enum1': 'EnumOne' } }
{ 'struct': 'UserDefZero',
'data': { 'integer': 'int' } }
Patch's effect on UserDefFlatUnion:
struct UserDefFlatUnion {
/* Members inherited from UserDefUnionBase: */
+ int64_t integer;
char *string;
EnumOne enum1;
/* Own members: */
union { /* union tag is @enum1 */
void *data;
UserDefA *value1;
UserDefB *value2;
UserDefB *value3;
};
};
Flat union visitors remain broken. They'll be fixed next.
Code is generated in a different order now, but that doesn't matter.
The two guards QAPI_TYPES_BUILTIN_STRUCT_DECL and
QAPI_TYPES_BUILTIN_CLEANUP_DECL are replaced by just
QAPI_TYPES_BUILTIN.
Two ugly special cases for simple unions now stand out like sore
thumbs:
1. The type tag is named 'type' everywhere, except in generated C,
where it's 'kind'.
2. QAPISchema lowers simple unions to semantically equivalent flat
unions. However, the C generated for a simple unions differs from
the C generated for its equivalent flat union, and we therefore
need special code to preserve that pointless difference for now.
Mark both TODO.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
2015-09-16 13:06:09 +02:00
|
|
|
|
2020-10-09 18:15:54 +02:00
|
|
|
def visit_array_type(self,
|
|
|
|
name: str,
|
|
|
|
info: Optional[QAPISourceInfo],
|
2021-08-04 10:30:57 +02:00
|
|
|
ifcond: QAPISchemaIfCond,
|
2020-10-09 18:15:54 +02:00
|
|
|
element_type: QAPISchemaType) -> None:
|
2018-07-03 17:56:45 +02:00
|
|
|
with ifcontext(ifcond, self._genh, self._genc):
|
|
|
|
self._genh.preamble_add(gen_fwd_object_or_array(name))
|
|
|
|
self._genh.add(gen_array(name, element_type))
|
|
|
|
self._gen_type_cleanup(name)
|
qapi-types: Convert to QAPISchemaVisitor, fixing flat unions
Fixes flat unions to get the base's base members. Test case is from
commit 2fc0043, in qapi-schema-test.json:
{ 'union': 'UserDefFlatUnion',
'base': 'UserDefUnionBase',
'discriminator': 'enum1',
'data': { 'value1' : 'UserDefA',
'value2' : 'UserDefB',
'value3' : 'UserDefB' } }
{ 'struct': 'UserDefUnionBase',
'base': 'UserDefZero',
'data': { 'string': 'str', 'enum1': 'EnumOne' } }
{ 'struct': 'UserDefZero',
'data': { 'integer': 'int' } }
Patch's effect on UserDefFlatUnion:
struct UserDefFlatUnion {
/* Members inherited from UserDefUnionBase: */
+ int64_t integer;
char *string;
EnumOne enum1;
/* Own members: */
union { /* union tag is @enum1 */
void *data;
UserDefA *value1;
UserDefB *value2;
UserDefB *value3;
};
};
Flat union visitors remain broken. They'll be fixed next.
Code is generated in a different order now, but that doesn't matter.
The two guards QAPI_TYPES_BUILTIN_STRUCT_DECL and
QAPI_TYPES_BUILTIN_CLEANUP_DECL are replaced by just
QAPI_TYPES_BUILTIN.
Two ugly special cases for simple unions now stand out like sore
thumbs:
1. The type tag is named 'type' everywhere, except in generated C,
where it's 'kind'.
2. QAPISchema lowers simple unions to semantically equivalent flat
unions. However, the C generated for a simple unions differs from
the C generated for its equivalent flat union, and we therefore
need special code to preserve that pointless difference for now.
Mark both TODO.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
2015-09-16 13:06:09 +02:00
|
|
|
|
2020-10-09 18:15:54 +02:00
|
|
|
def visit_object_type(self,
|
|
|
|
name: str,
|
|
|
|
info: Optional[QAPISourceInfo],
|
2021-08-04 10:30:57 +02:00
|
|
|
ifcond: QAPISchemaIfCond,
|
2020-10-09 18:15:54 +02:00
|
|
|
features: List[QAPISchemaFeature],
|
|
|
|
base: Optional[QAPISchemaObjectType],
|
|
|
|
members: List[QAPISchemaObjectTypeMember],
|
|
|
|
variants: Optional[QAPISchemaVariants]) -> None:
|
qapi: Emit implicit structs in generated C
We already have several places that want to visit all the members
of an implicit object within a larger context (simple union variant,
event with anonymous data, command with anonymous arguments struct);
and will be adding another one soon (the ability to declare an
anonymous base for a flat union). Having a C struct declared for
these implicit types, along with a visit_type_FOO_members() helper
function, will make for fewer special cases in our generator.
We do not, however, need qapi_free_FOO() or visit_type_FOO()
functions for implicit types, because they should not be used
directly outside of the generated code. This is done by adding a
conditional in visit_object_type() for both qapi-types.py and
qapi-visit.py based on the object name. The comparison of
"name.startswith('q_')" is a bit hacky (it's basically duplicating
what .is_implicit() already uses), but beats changing the signature
of the visit_object_type() callback to pass a new 'implicit' flag.
The hack should be temporary: we are considering adding a future
patch that consolidates the narrow visit_object_type(..., base,
local_members, variants) and visit_object_type_flat(...,
all_members, variants) [where different sets of information are
already broken out, and the QAPISchemaObjectType is no longer
available] into a broader visit_object_type(obj_type) [where the
visitor can query the needed fields from obj_type directly].
Also, now that we WANT to output C code for implicits, we no longer
need the visit_needed() filter, leaving 'q_empty' as the only object
still needing a special case. Remember, 'q_empty' is the only
built-in generated object, which means that without a special case
it would be emitted in multiple files (the main qapi-types.h and in
qga-qapi-types.h) causing compilation failure due to redefinition.
But since it has no members, it's easier to just avoid an attempt to
visit that particular type; since gen_object() is called recursively,
we also prime the objects_seen set to cover any recursion into the
empty type.
The patch relies on the changed naming of implicit types in the
previous patch. It is a bit unfortunate that the generated struct
names and visit_type_FOO_members() don't match normal naming
conventions, but it's not too bad, since they will only be used in
generated code.
The generated code grows substantially in size: the implicit
'-wrapper' types must be emitted in qapi-types.h before any union
can include an unboxed member of that type. Arguably, the '-args'
types could be emitted in a private header for just qapi-visit.c
and qmp-marshal.c, rather than polluting qapi-types.h; but adding
complexity to the generator to split the output location according
to role doesn't seem worth the maintenance costs.
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1458254921-17042-6-git-send-email-eblake@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-03-17 23:48:30 +01:00
|
|
|
# Nothing to do for the special empty builtin
|
|
|
|
if name == 'q_empty':
|
|
|
|
return
|
2018-07-03 17:56:45 +02:00
|
|
|
with ifcontext(ifcond, self._genh):
|
|
|
|
self._genh.preamble_add(gen_fwd_object_or_array(name))
|
|
|
|
self._genh.add(gen_object(name, ifcond, base, members, variants))
|
|
|
|
with ifcontext(ifcond, self._genh, self._genc):
|
|
|
|
if base and not base.is_implicit():
|
|
|
|
self._genh.add(gen_upcast(name, base))
|
|
|
|
# TODO Worth changing the visitor signature, so we could
|
|
|
|
# directly use rather than repeat type.is_implicit()?
|
|
|
|
if not name.startswith('q_'):
|
|
|
|
# implicit types won't be directly allocated/freed
|
|
|
|
self._gen_type_cleanup(name)
|
qapi-types: Convert to QAPISchemaVisitor, fixing flat unions
Fixes flat unions to get the base's base members. Test case is from
commit 2fc0043, in qapi-schema-test.json:
{ 'union': 'UserDefFlatUnion',
'base': 'UserDefUnionBase',
'discriminator': 'enum1',
'data': { 'value1' : 'UserDefA',
'value2' : 'UserDefB',
'value3' : 'UserDefB' } }
{ 'struct': 'UserDefUnionBase',
'base': 'UserDefZero',
'data': { 'string': 'str', 'enum1': 'EnumOne' } }
{ 'struct': 'UserDefZero',
'data': { 'integer': 'int' } }
Patch's effect on UserDefFlatUnion:
struct UserDefFlatUnion {
/* Members inherited from UserDefUnionBase: */
+ int64_t integer;
char *string;
EnumOne enum1;
/* Own members: */
union { /* union tag is @enum1 */
void *data;
UserDefA *value1;
UserDefB *value2;
UserDefB *value3;
};
};
Flat union visitors remain broken. They'll be fixed next.
Code is generated in a different order now, but that doesn't matter.
The two guards QAPI_TYPES_BUILTIN_STRUCT_DECL and
QAPI_TYPES_BUILTIN_CLEANUP_DECL are replaced by just
QAPI_TYPES_BUILTIN.
Two ugly special cases for simple unions now stand out like sore
thumbs:
1. The type tag is named 'type' everywhere, except in generated C,
where it's 'kind'.
2. QAPISchema lowers simple unions to semantically equivalent flat
unions. However, the C generated for a simple unions differs from
the C generated for its equivalent flat union, and we therefore
need special code to preserve that pointless difference for now.
Mark both TODO.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
2015-09-16 13:06:09 +02:00
|
|
|
|
2020-10-09 18:15:54 +02:00
|
|
|
def visit_alternate_type(self,
|
|
|
|
name: str,
|
2021-02-01 20:37:46 +01:00
|
|
|
info: Optional[QAPISourceInfo],
|
2021-08-04 10:30:57 +02:00
|
|
|
ifcond: QAPISchemaIfCond,
|
2020-10-09 18:15:54 +02:00
|
|
|
features: List[QAPISchemaFeature],
|
|
|
|
variants: QAPISchemaVariants) -> None:
|
2018-07-03 17:56:45 +02:00
|
|
|
with ifcontext(ifcond, self._genh):
|
|
|
|
self._genh.preamble_add(gen_fwd_object_or_array(name))
|
|
|
|
self._genh.add(gen_object(name, ifcond, None,
|
2018-02-26 20:50:08 +01:00
|
|
|
[variants.tag_member], variants))
|
2018-07-03 17:56:45 +02:00
|
|
|
with ifcontext(ifcond, self._genh, self._genc):
|
|
|
|
self._gen_type_cleanup(name)
|
qapi-types: Convert to QAPISchemaVisitor, fixing flat unions
Fixes flat unions to get the base's base members. Test case is from
commit 2fc0043, in qapi-schema-test.json:
{ 'union': 'UserDefFlatUnion',
'base': 'UserDefUnionBase',
'discriminator': 'enum1',
'data': { 'value1' : 'UserDefA',
'value2' : 'UserDefB',
'value3' : 'UserDefB' } }
{ 'struct': 'UserDefUnionBase',
'base': 'UserDefZero',
'data': { 'string': 'str', 'enum1': 'EnumOne' } }
{ 'struct': 'UserDefZero',
'data': { 'integer': 'int' } }
Patch's effect on UserDefFlatUnion:
struct UserDefFlatUnion {
/* Members inherited from UserDefUnionBase: */
+ int64_t integer;
char *string;
EnumOne enum1;
/* Own members: */
union { /* union tag is @enum1 */
void *data;
UserDefA *value1;
UserDefB *value2;
UserDefB *value3;
};
};
Flat union visitors remain broken. They'll be fixed next.
Code is generated in a different order now, but that doesn't matter.
The two guards QAPI_TYPES_BUILTIN_STRUCT_DECL and
QAPI_TYPES_BUILTIN_CLEANUP_DECL are replaced by just
QAPI_TYPES_BUILTIN.
Two ugly special cases for simple unions now stand out like sore
thumbs:
1. The type tag is named 'type' everywhere, except in generated C,
where it's 'kind'.
2. QAPISchema lowers simple unions to semantically equivalent flat
unions. However, the C generated for a simple unions differs from
the C generated for its equivalent flat union, and we therefore
need special code to preserve that pointless difference for now.
Mark both TODO.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
2015-09-16 13:06:09 +02:00
|
|
|
|
2011-12-27 15:02:16 +01:00
|
|
|
|
2020-10-09 18:15:54 +02:00
|
|
|
def gen_types(schema: QAPISchema,
|
|
|
|
output_dir: str,
|
|
|
|
prefix: str,
|
|
|
|
opt_builtins: bool) -> None:
|
qapi/types qapi/visit: Generate built-in stuff into separate files
Linking code from multiple separate QAPI schemata into the same
program is possible, but involves some weirdness around built-in
types:
* We generate code for built-in types into .c only with option
--builtins. The user is responsible for generating code for exactly
one QAPI schema per program with --builtins.
* We generate code for built-in types into .h regardless of
--builtins, but guarded by #ifndef QAPI_VISIT_BUILTIN. Because all
copies of this code are exactly the same, including any combination
of these headers works.
Replace this contraption by something more conventional: generate code
for built-in types into their very own files: qapi-builtin-types.c,
qapi-builtin-visit.c, qapi-builtin-types.h, qapi-builtin-visit.h, but
only with --builtins. Obey --output-dir, but ignore --prefix for
them.
Make qapi-types.h include qapi-builtin-types.h. With multiple
schemata you now have multiple qapi-types.[ch], but only one
qapi-builtin-types.[ch]. Same for qapi-visit.[ch] and
qapi-builtin-visit.[ch].
Bonus: if all you need is built-in stuff, you can include a much
smaller header. To be exploited shortly.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Message-Id: <20180211093607.27351-21-armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Michael Roth <mdroth@linux.vnet.ibm.com>
[eblake: fix octal constant for python 3]
Signed-off-by: Eric Blake <eblake@redhat.com>
2018-02-26 23:29:21 +01:00
|
|
|
vis = QAPISchemaGenTypeVisitor(prefix)
|
2018-02-26 20:39:37 +01:00
|
|
|
schema.visit(vis)
|
qapi/types qapi/visit: Generate built-in stuff into separate files
Linking code from multiple separate QAPI schemata into the same
program is possible, but involves some weirdness around built-in
types:
* We generate code for built-in types into .c only with option
--builtins. The user is responsible for generating code for exactly
one QAPI schema per program with --builtins.
* We generate code for built-in types into .h regardless of
--builtins, but guarded by #ifndef QAPI_VISIT_BUILTIN. Because all
copies of this code are exactly the same, including any combination
of these headers works.
Replace this contraption by something more conventional: generate code
for built-in types into their very own files: qapi-builtin-types.c,
qapi-builtin-visit.c, qapi-builtin-types.h, qapi-builtin-visit.h, but
only with --builtins. Obey --output-dir, but ignore --prefix for
them.
Make qapi-types.h include qapi-builtin-types.h. With multiple
schemata you now have multiple qapi-types.[ch], but only one
qapi-builtin-types.[ch]. Same for qapi-visit.[ch] and
qapi-builtin-visit.[ch].
Bonus: if all you need is built-in stuff, you can include a much
smaller header. To be exploited shortly.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Message-Id: <20180211093607.27351-21-armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Michael Roth <mdroth@linux.vnet.ibm.com>
[eblake: fix octal constant for python 3]
Signed-off-by: Eric Blake <eblake@redhat.com>
2018-02-26 23:29:21 +01:00
|
|
|
vis.write(output_dir, opt_builtins)
|