mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2025-03-24 22:25:11 +00:00
qapi-event: Utilize implicit struct visits
Rather than generate inline per-member visits, take advantage of the 'visit_type_FOO_members()' function for emitting events. This is possible now that implicit structs can be visited like any other. Generated code shrinks accordingly; by initializing a struct based on parameters, through a new gen_param_var() helper, like: |@@ -338,6 +250,9 @@ void qapi_event_send_block_job_error(con | QMPEventFuncEmit emit = qmp_event_get_func_emit(); | QmpOutputVisitor *qov; | Visitor *v; |+ q_obj_BLOCK_JOB_ERROR_arg param = { |+ (char *)device, operation, action |+ }; | | if (!emit) { | return; @@ -351,19 +266,7 @@ void qapi_event_send_block_job_error(con | if (err) { | goto out; | } |- visit_type_str(v, "device", (char **)&device, &err); |- if (err) { |- goto out_obj; |- } |- visit_type_IoOperationType(v, "operation", &operation, &err); |- if (err) { |- goto out_obj; |- } |- visit_type_BlockErrorAction(v, "action", &action, &err); |- if (err) { |- goto out_obj; |- } |-out_obj: |+ visit_type_q_obj_BLOCK_JOB_ERROR_arg_members(v, ¶m, &err); | visit_end_struct(v, err ? NULL : &err); Notice that the initialization of 'param' has to cast away const (just as the old gen_visit_members() had to do): we can't change the signature of the user function (which uses 'const char *'), but have to assign it to a non-const QAPI object (which requires 'char *'). While touching this, document with a FIXME comment that there is still a potential collision between QMP members and our choice of local variable names within qapi_event_send_FOO(). This patch also paves the way for some followup simplifications in the generator, in subsequent patches. Backports commit 0949e95b48e30715e157cabbc59dcb0ed912d3ff from qemu
This commit is contained in:
parent
eb4b02705a
commit
a86b89f166
|
@ -27,7 +27,37 @@ def gen_event_send_decl(name, arg_type):
|
||||||
proto=gen_event_send_proto(name, arg_type))
|
proto=gen_event_send_proto(name, arg_type))
|
||||||
|
|
||||||
|
|
||||||
|
# Declare and initialize an object 'qapi' using parameters from gen_params()
|
||||||
|
def gen_param_var(typ):
|
||||||
|
assert not typ.variants
|
||||||
|
ret = mcgen('''
|
||||||
|
%(c_name)s param = {
|
||||||
|
''',
|
||||||
|
c_name=typ.c_name())
|
||||||
|
sep = ' '
|
||||||
|
for memb in typ.members:
|
||||||
|
ret += sep
|
||||||
|
sep = ', '
|
||||||
|
if memb.optional:
|
||||||
|
ret += 'has_' + c_name(memb.name) + sep
|
||||||
|
if memb.type.name == 'str':
|
||||||
|
# Cast away const added in gen_params()
|
||||||
|
ret += '(char *)'
|
||||||
|
ret += c_name(memb.name)
|
||||||
|
ret += mcgen('''
|
||||||
|
|
||||||
|
};
|
||||||
|
''')
|
||||||
|
return ret
|
||||||
|
|
||||||
|
|
||||||
def gen_event_send(name, arg_type):
|
def gen_event_send(name, arg_type):
|
||||||
|
# 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
|
||||||
|
# practice, we can rename our local variables with a leading _ prefix,
|
||||||
|
# or split the code into a wrapper function that creates a boxed
|
||||||
|
# 'param' object then calls another to do the real work.
|
||||||
ret = mcgen('''
|
ret = mcgen('''
|
||||||
|
|
||||||
%(proto)s
|
%(proto)s
|
||||||
|
@ -43,10 +73,11 @@ def gen_event_send(name, arg_type):
|
||||||
ret += mcgen('''
|
ret += mcgen('''
|
||||||
QmpOutputVisitor *qov;
|
QmpOutputVisitor *qov;
|
||||||
Visitor *v;
|
Visitor *v;
|
||||||
|
|
||||||
''')
|
''')
|
||||||
|
ret += gen_param_var(arg_type)
|
||||||
|
|
||||||
ret += mcgen('''
|
ret += mcgen('''
|
||||||
|
|
||||||
emit = qmp_event_get_func_emit();
|
emit = qmp_event_get_func_emit();
|
||||||
if (!emit) {
|
if (!emit) {
|
||||||
return;
|
return;
|
||||||
|
@ -60,24 +91,21 @@ def gen_event_send(name, arg_type):
|
||||||
if arg_type and arg_type.members:
|
if arg_type and arg_type.members:
|
||||||
ret += mcgen('''
|
ret += mcgen('''
|
||||||
qov = qmp_output_visitor_new();
|
qov = qmp_output_visitor_new();
|
||||||
|
|
||||||
v = qmp_output_get_visitor(qov);
|
v = qmp_output_get_visitor(qov);
|
||||||
|
|
||||||
visit_start_struct(v, "%(name)s", NULL, 0, &err);
|
visit_start_struct(v, "%(name)s", NULL, 0, &err);
|
||||||
''',
|
if (err) {
|
||||||
name=name)
|
goto out;
|
||||||
ret += gen_err_check()
|
}
|
||||||
ret += gen_visit_members(arg_type.members, need_cast=True,
|
visit_type_%(c_name)s_members(v, ¶m, &err);
|
||||||
label='out_obj')
|
|
||||||
ret += mcgen('''
|
|
||||||
out_obj:
|
|
||||||
visit_end_struct(v, err ? NULL : &err);
|
visit_end_struct(v, err ? NULL : &err);
|
||||||
if (err) {
|
if (err) {
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
qdict_put_obj(qmp, "data", qmp_output_get_qobject(qov));
|
qdict_put_obj(qmp, "data", qmp_output_get_qobject(qov));
|
||||||
''')
|
''',
|
||||||
|
name=name, c_name=arg_type.c_name())
|
||||||
|
|
||||||
ret += mcgen('''
|
ret += mcgen('''
|
||||||
emit(%(c_enum)s, qmp, &err);
|
emit(%(c_enum)s, qmp, &err);
|
||||||
|
|
Loading…
Reference in a new issue