mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2024-12-23 13:05:28 +00:00
qapi: Plumb in 'boxed' to qapi generator lower levels
The next patch will add support for passing a qapi union type as the 'data' of a command. But to do that, the user function for implementing the command, as called by the generated marshal command, must take the corresponding C struct as a single boxed pointer, rather than a breakdown into one parameter per member. Even without a union, being able to use a C struct rather than a list of parameters can make it much easier to handle coding with QAPI. This patch adds the internal plumbing of a 'boxed' flag associated with each command and event. In several cases, this means adding indentation, with one new dead branch and the remaining branch being the original code more deeply nested; this was done so that the new implementation in the next patch is easier to review without also being mixed with indentation changes. For this patch, no behavior or generated output changes, other than the testsuite outputting the value of the new flag (always False for now). Backports commit 48825ca419fd9c8140d4fecb24e982d68ebca74f from qemu
This commit is contained in:
parent
6ff318b839
commit
c65f056fbe
|
@ -13,18 +13,18 @@
|
|||
|
||||
from qapi import *
|
||||
|
||||
def gen_event_send_proto(name, arg_type):
|
||||
def gen_event_send_proto(name, arg_type, boxed):
|
||||
return 'void qapi_event_send_%(c_name)s(%(param)s)' % {
|
||||
'c_name': c_name(name.lower()),
|
||||
'param': gen_params(arg_type, 'Error **errp')}
|
||||
'param': gen_params(arg_type, boxed, 'Error **errp')}
|
||||
|
||||
|
||||
def gen_event_send_decl(name, arg_type):
|
||||
def gen_event_send_decl(name, arg_type, boxed):
|
||||
return mcgen('''
|
||||
|
||||
%(proto)s;
|
||||
''',
|
||||
proto=gen_event_send_proto(name, arg_type))
|
||||
proto=gen_event_send_proto(name, arg_type, boxed))
|
||||
|
||||
|
||||
# Declare and initialize an object 'qapi' using parameters from gen_params()
|
||||
|
@ -56,7 +56,7 @@ def gen_param_var(typ):
|
|||
return ret
|
||||
|
||||
|
||||
def gen_event_send(name, arg_type):
|
||||
def gen_event_send(name, arg_type, boxed):
|
||||
# FIXME: Our declaration of local variables (and of 'errp' in the
|
||||
# parameter list) can collide with exploded members of the event's
|
||||
# data type passed in as parameters. If this collision ever hits in
|
||||
|
@ -71,7 +71,7 @@ def gen_event_send(name, arg_type):
|
|||
Error *err = NULL;
|
||||
QMPEventFuncEmit emit;
|
||||
''',
|
||||
proto=gen_event_send_proto(name, arg_type))
|
||||
proto=gen_event_send_proto(name, arg_type, boxed))
|
||||
|
||||
if arg_type and not arg_type.is_empty():
|
||||
assert not arg_type.variants
|
||||
|
@ -160,9 +160,9 @@ class QAPISchemaGenEventVisitor(QAPISchemaVisitor):
|
|||
self.defn += gen_enum_lookup(event_enum_name, self._event_names)
|
||||
self._event_names = None;
|
||||
|
||||
def visit_event(self, name, info, arg_type):
|
||||
self.decl += gen_event_send_decl(name, arg_type)
|
||||
self.defn += gen_event_send(name, arg_type)
|
||||
def visit_event(self, name, info, arg_type, boxed):
|
||||
self.decl += gen_event_send_decl(name, arg_type, boxed)
|
||||
self.defn += gen_event_send(name, arg_type, boxed)
|
||||
self._event_names.append(name)
|
||||
|
||||
(input_file, output_dir, do_c, do_h, prefix, dummy) = parse_command_line()
|
||||
|
|
|
@ -831,10 +831,10 @@ class QAPISchemaVisitor(object):
|
|||
pass
|
||||
|
||||
def visit_command(self, name, info, arg_type, ret_type,
|
||||
gen, success_response):
|
||||
gen, success_response, boxed):
|
||||
pass
|
||||
|
||||
def visit_event(self, name, info, arg_type):
|
||||
def visit_event(self, name, info, arg_type, boxed):
|
||||
pass
|
||||
|
||||
|
||||
|
@ -1179,7 +1179,8 @@ class QAPISchemaAlternateType(QAPISchemaType):
|
|||
|
||||
|
||||
class QAPISchemaCommand(QAPISchemaEntity):
|
||||
def __init__(self, name, info, arg_type, ret_type, gen, success_response):
|
||||
def __init__(self, name, info, arg_type, ret_type, gen, success_response,
|
||||
boxed):
|
||||
QAPISchemaEntity.__init__(self, name, info)
|
||||
assert not arg_type or isinstance(arg_type, str)
|
||||
assert not ret_type or isinstance(ret_type, str)
|
||||
|
@ -1189,12 +1190,14 @@ class QAPISchemaCommand(QAPISchemaEntity):
|
|||
self.ret_type = None
|
||||
self.gen = gen
|
||||
self.success_response = success_response
|
||||
self.boxed = boxed
|
||||
|
||||
def check(self, schema):
|
||||
if self._arg_type_name:
|
||||
self.arg_type = schema.lookup_type(self._arg_type_name)
|
||||
assert isinstance(self.arg_type, QAPISchemaObjectType)
|
||||
assert not self.arg_type.variants # not implemented
|
||||
assert not self.boxed # not implemented
|
||||
if self._ret_type_name:
|
||||
self.ret_type = schema.lookup_type(self._ret_type_name)
|
||||
assert isinstance(self.ret_type, QAPISchemaType)
|
||||
|
@ -1202,24 +1205,26 @@ class QAPISchemaCommand(QAPISchemaEntity):
|
|||
def visit(self, visitor):
|
||||
visitor.visit_command(self.name, self.info,
|
||||
self.arg_type, self.ret_type,
|
||||
self.gen, self.success_response)
|
||||
self.gen, self.success_response, self.boxed)
|
||||
|
||||
|
||||
class QAPISchemaEvent(QAPISchemaEntity):
|
||||
def __init__(self, name, info, arg_type):
|
||||
def __init__(self, name, info, arg_type, boxed):
|
||||
QAPISchemaEntity.__init__(self, name, info)
|
||||
assert not arg_type or isinstance(arg_type, str)
|
||||
self._arg_type_name = arg_type
|
||||
self.arg_type = None
|
||||
self.boxed = boxed
|
||||
|
||||
def check(self, schema):
|
||||
if self._arg_type_name:
|
||||
self.arg_type = schema.lookup_type(self._arg_type_name)
|
||||
assert isinstance(self.arg_type, QAPISchemaObjectType)
|
||||
assert not self.arg_type.variants # not implemented
|
||||
assert not self.boxed # not implemented
|
||||
|
||||
def visit(self, visitor):
|
||||
visitor.visit_event(self.name, self.info, self.arg_type)
|
||||
visitor.visit_event(self.name, self.info, self.arg_type, self.boxed)
|
||||
|
||||
|
||||
class QAPISchema(object):
|
||||
|
@ -1395,6 +1400,7 @@ class QAPISchema(object):
|
|||
rets = expr.get('returns')
|
||||
gen = expr.get('gen', True)
|
||||
success_response = expr.get('success-response', True)
|
||||
boxed = expr.get('boxed', False)
|
||||
if isinstance(data, OrderedDict):
|
||||
data = self._make_implicit_object_type(
|
||||
name, info, 'arg', self._make_members(data, info))
|
||||
|
@ -1402,15 +1408,16 @@ class QAPISchema(object):
|
|||
assert len(rets) == 1
|
||||
rets = self._make_array_type(rets[0], info)
|
||||
self._def_entity(QAPISchemaCommand(name, info, data, rets, gen,
|
||||
success_response))
|
||||
success_response, boxed))
|
||||
|
||||
def _def_event(self, expr, info):
|
||||
name = expr['event']
|
||||
data = expr.get('data')
|
||||
boxed = expr.get('boxed', False)
|
||||
if isinstance(data, OrderedDict):
|
||||
data = self._make_implicit_object_type(
|
||||
name, info, 'arg', self._make_members(data, info))
|
||||
self._def_entity(QAPISchemaEvent(name, info, data))
|
||||
self._def_entity(QAPISchemaEvent(name, info, data, boxed))
|
||||
|
||||
def _def_exprs(self):
|
||||
for expr_elem in self.exprs:
|
||||
|
@ -1652,18 +1659,20 @@ extern const char *const %(c_name)s_lookup[];
|
|||
return ret
|
||||
|
||||
|
||||
def gen_params(arg_type, extra):
|
||||
def gen_params(arg_type, boxed, extra):
|
||||
if not arg_type:
|
||||
return extra
|
||||
assert not arg_type.variants
|
||||
ret = ''
|
||||
sep = ''
|
||||
for memb in arg_type.members:
|
||||
ret += sep
|
||||
sep = ', '
|
||||
if memb.optional:
|
||||
ret += 'bool has_%s, ' % c_name(memb.name)
|
||||
ret += '%s %s' % (memb.type.c_param_type(), c_name(memb.name))
|
||||
if boxed:
|
||||
assert False # not implemented
|
||||
else:
|
||||
assert not arg_type.variants
|
||||
for memb in arg_type.members:
|
||||
ret += sep
|
||||
sep = ', '
|
||||
if memb.optional:
|
||||
ret += 'bool has_%s, ' % c_name(memb.name)
|
||||
ret += '%s %s' % (memb.type.c_param_type(),
|
||||
c_name(memb.name))
|
||||
if extra:
|
||||
ret += sep + extra
|
||||
return ret
|
||||
|
|
Loading…
Reference in a new issue