1. 18 3月, 2016 3 次提交
    • E
      qapi: Don't special-case simple union wrappers · 32bafa8f
      Eric Blake 提交于
      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: NEric Blake <eblake@redhat.com>
      Message-Id: <1458254921-17042-13-git-send-email-eblake@redhat.com>
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      32bafa8f
    • E
      qapi: Inline gen_visit_members() into lone caller · 12f254fd
      Eric Blake 提交于
      Commit 82ca8e46 noticed that we had multiple implementations of
      visiting every member of a struct, and consolidated it into
      gen_visit_fields() (now gen_visit_members()) with enough
      parameters to cater to slight differences between the clients.
      But recent exposure of implicit types has meant that we are now
      down to a single use of that method, so we can clean up the
      unused conditionals and just inline it into the remaining
      caller: gen_visit_object_members().
      
      Likewise, gen_err_check() no longer needs optional parameters,
      as the lone use of non-defaults was via gen_visit_members().
      
      No change to generated code.
      Suggested-by: NMarkus Armbruster <armbru@redhat.com>
      Signed-off-by: NEric Blake <eblake@redhat.com>
      Message-Id: <1458254921-17042-11-git-send-email-eblake@redhat.com>
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      12f254fd
    • E
      qapi: Emit implicit structs in generated C · 7ce106a9
      Eric Blake 提交于
      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: NEric Blake <eblake@redhat.com>
      Message-Id: <1458254921-17042-6-git-send-email-eblake@redhat.com>
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      7ce106a9
  2. 05 3月, 2016 3 次提交
    • E
      qapi-visit: Expose visit_type_FOO_members() · 4d91e911
      Eric Blake 提交于
      Dan Berrange reported a case where he needs to work with a
      QCryptoBlockOptions union type using the OptsVisitor, but only
      visit one of the branches of that type (the discriminator is not
      visited directly, but learned externally).  When things were
      boxed, it was easy: just visit the variant directly, which took
      care of both allocating the variant and visiting its members, then
      store that pointer in the union type.  But now that things are
      unboxed, we need a way to visit the members without allocation,
      done by exposing visit_type_FOO_members() to the user.
      
      Before the patch, we had quite a bit of code associated with
      object_members_seen to make sure that a declaration of the helper
      was in scope before any use of the function.  But now that the
      helper is public and declared in the header, the .c file no
      longer needs to worry about topological sorting (the helper is
      always in scope), which leads to some nice cleanups.
      Signed-off-by: NEric Blake <eblake@redhat.com>
      Message-Id: <1457021813-10704-4-git-send-email-eblake@redhat.com>
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      4d91e911
    • E
      qapi: Rename 'fields' to 'members' in generated C code · c81200b0
      Eric Blake 提交于
      C types and JSON objects don't have fields, but members.  We
      shouldn't gratuitously invent terminology.  This patch is a
      strict renaming of static genarated functions, plus the naming
      of the dummy filler member for empty structs, before the next
      patch exposes some of that naming to the rest of the code base.
      Suggested-by: NMarkus Armbruster <armbru@redhat.com>
      Signed-off-by: NEric Blake <eblake@redhat.com>
      Message-Id: <1457021813-10704-3-git-send-email-eblake@redhat.com>
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      c81200b0
    • E
      qapi: Rename 'fields' to 'members' in generator · 14f00c6c
      Eric Blake 提交于
      C types and JSON objects don't have fields, but members.  We
      shouldn't gratuitously invent terminology.  This patch is a
      strict renaming of generator code internals (including testsuite
      comments), before later patches rename C interfaces.
      
      No change to generated code with this patch.
      Suggested-by: NMarkus Armbruster <armbru@redhat.com>
      Signed-off-by: NEric Blake <eblake@redhat.com>
      Message-Id: <1457021813-10704-2-git-send-email-eblake@redhat.com>
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      14f00c6c
  3. 19 2月, 2016 10 次提交
    • E
      qapi: Change visit_start_implicit_struct to visit_start_alternate · dbf11922
      Eric Blake 提交于
      After recent changes, the only remaining use of
      visit_start_implicit_struct() is for allocating the space needed
      when visiting an alternate.  Since the term 'implicit struct' is
      hard to explain, rename the function to its current usage.  While
      at it, we can merge the functionality of visit_get_next_type()
      into the same function, making it more like visit_start_struct().
      
      Generated code is now slightly smaller:
      
      | {
      |     Error *err = NULL;
      |
      |-    visit_start_implicit_struct(v, (void**) obj, sizeof(BlockdevRef), &err);
      |+    visit_start_alternate(v, name, (GenericAlternate **)obj, sizeof(**obj),
      |+                          true, &err);
      |     if (err) {
      |         goto out;
      |     }
      |-    visit_get_next_type(v, name, &(*obj)->type, true, &err);
      |-    if (err) {
      |-        goto out_obj;
      |-    }
      |     switch ((*obj)->type) {
      |     case QTYPE_QDICT:
      |         visit_start_struct(v, name, NULL, 0, &err);
      ...
      |     }
      |-out_obj:
      |-    visit_end_implicit_struct(v);
      |+    visit_end_alternate(v);
      | out:
      |     error_propagate(errp, err);
      | }
      Signed-off-by: NEric Blake <eblake@redhat.com>
      Message-Id: <1455778109-6278-16-git-send-email-eblake@redhat.com>
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      dbf11922
    • E
      qapi: Don't box branches of flat unions · 544a3731
      Eric Blake 提交于
      There's no reason to do two malloc's for a flat union; let's just
      inline the branch struct directly into the C union branch of the
      flat union.
      
      Surprisingly, fewer clients were actually using explicit references
      to the branch types in comparison to the number of flat unions
      thus modified.
      
      This lets us reduce the hack in qapi-types:gen_variants() added in
      the previous patch; we no longer need to distinguish between
      alternates and flat unions.
      
      The change to unboxed structs means that u.data (added in commit
      cee2dedb) is now coincident with random fields of each branch of
      the flat union, whereas beforehand it was only coincident with
      pointers (since all branches of a flat union have to be objects).
      Note that this was already the case for simple unions - but there
      we got lucky.  Remember, visit_start_union() blindly returns true
      for all visitors except for the dealloc visitor, where it returns
      the value !!obj->u.data, and that this result then controls
      whether to proceed with the visit to the variant.  Pre-patch,
      this meant that flat unions were testing whether the boxed pointer
      was still NULL, and thereby skipping visit_end_implicit_struct()
      and avoiding a NULL dereference if the pointer had not been
      allocated.  The same was true for simple unions where the current
      branch had pointer type, except there we bypassed visit_type_FOO().
      But for simple unions where the current branch had scalar type, the
      contents of that scalar meant that the decision to call
      visit_type_FOO() was data-dependent - the reason we got lucky there
      is that visit_type_FOO() for all scalar types in the dealloc visitor
      is a no-op (only the pointer variants had anything to free), so it
      did not matter whether the dealloc visit was skipped.  But with this
      patch, we would risk leaking memory if we could skip a call to
      visit_type_FOO_fields() based solely on a data-dependent decision.
      
      But notice: in the dealloc visitor, visit_type_FOO() already handles
      a NULL obj - it was only the visit_type_implicit_FOO() that was
      failing to check for NULL. And now that we have refactored things to
      have the branch be part of the parent struct, we no longer have a
      separate pointer that can be NULL in the first place.  So we can just
      delete the call to visit_start_union() altogether, and blindly visit
      the branch type; there is no change in behavior except to the dealloc
      visitor, where we now unconditionally visit the branch, but where that
      visit is now always safe (for a flat union, we can no longer
      dereference NULL, and for a simple union, visit_type_FOO() was already
      safely handling NULL on pointer types).
      
      Unfortunately, simple unions are not as easy to switch to unboxed
      layout; because we are special-casing the hidden implicit type with
      a single 'data' member, we really DO need to keep calling another
      layer of visit_start_struct(), with a second malloc; although there
      are some cleanups planned for simple unions in later patches.
      
      visit_start_union() and gen_visit_implicit_struct() are now unused.
      Drop them.
      
      Note that after this patch, the only remaining use of
      visit_start_implicit_struct() is for alternate types; the next patch
      will do further cleanup based on that fact.
      Signed-off-by: NEric Blake <eblake@redhat.com>
      Message-Id: <1455778109-6278-14-git-send-email-eblake@redhat.com>
      [Dead code deletion squashed in, commit message updated accordingly]
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      544a3731
    • E
      qapi: Don't box struct branch of alternate · becceedc
      Eric Blake 提交于
      There's no reason to do two malloc's for an alternate type visiting
      a QAPI struct; let's just inline the struct directly as the C union
      branch of the struct.
      
      Surprisingly, no clients were actually using the struct member prior
      to this patch outside of the testsuite; an earlier patch in the series
      added some testsuite coverage to make the effect of this patch more
      obvious.
      
      In qapi.py, c_type() gains a new is_unboxed flag to control when we
      are emitting a C struct unboxed within the context of an outer
      struct (different from our other two modes of usage with no flags
      for normal local variable declarations, and with is_param for adding
      'const' in a parameter list).  I don't know if there is any more
      pythonic way of collapsing the two flags into a single parameter,
      as we never have a caller setting both flags at once.
      
      Ultimately, we want to also unbox branches for QAPI unions, but as
      that touches a lot more client code, it is better as separate
      patches.  But since unions and alternates share gen_variants(), I
      had to hack in a way to test if we are visiting an alternate type
      for setting the is_unboxed flag: look for a non-object branch.
      This works because alternates have at least two branches, with at
      most one object branch, while unions have only object branches.
      The hack will go away in a later patch.
      
      The generated code difference to qapi-types.h is relatively small:
      
      | struct BlockdevRef {
      |     QType type;
      |     union { /* union tag is @type */
      |         void *data;
      |-        BlockdevOptions *definition;
      |+        BlockdevOptions definition;
      |         char *reference;
      |     } u;
      | };
      
      The corresponding spot in qapi-visit.c calls visit_type_FOO(), which
      first calls visit_start_struct() to allocate or deallocate the member
      and handle a layer of {} from the JSON stream, then visits the
      members.  To peel off the indirection and the memory management that
      comes with it, we inline this call, then suppress allocation /
      deallocation by passing NULL to visit_start_struct(), and adjust the
      member visit:
      
      |     switch ((*obj)->type) {
      |     case QTYPE_QDICT:
      |-        visit_type_BlockdevOptions(v, name, &(*obj)->u.definition, &err);
      |+        visit_start_struct(v, name, NULL, 0, &err);
      |+        if (err) {
      |+            break;
      |+        }
      |+        visit_type_BlockdevOptions_fields(v, &(*obj)->u.definition, &err);
      |+        error_propagate(errp, err);
      |+        err = NULL;
      |+        visit_end_struct(v, &err);
      |         break;
      |     case QTYPE_QSTRING:
      |         visit_type_str(v, name, &(*obj)->u.reference, &err);
      
      The visit of non-object fields is unchanged.
      Signed-off-by: NEric Blake <eblake@redhat.com>
      Message-Id: <1455778109-6278-13-git-send-email-eblake@redhat.com>
      [Commit message tweaked]
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      becceedc
    • E
      qapi-visit: Use common idiom in gen_visit_fields_decl() · 2208d649
      Eric Blake 提交于
      We have several instances of methods that do an early exit if
      output is not needed, then log that output is being generated,
      and finally produce the output; see qapi-types.py:gen_object()
      and qapi-visit.py:gen_visit_implicit_struct().  The odd man
      out was gen_visit_fields_decl(); rearrange it to be more like
      the others.  No semantic change or difference to generated code.
      Signed-off-by: NEric Blake <eblake@redhat.com>
      Message-Id: <1455778109-6278-12-git-send-email-eblake@redhat.com>
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      2208d649
    • E
      qapi: Adjust layout of FooList types · e65d89bf
      Eric Blake 提交于
      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: NEric Blake <eblake@redhat.com>
      Message-Id: <1455778109-6278-10-git-send-email-eblake@redhat.com>
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      e65d89bf
    • E
      qapi-visit: Less indirection in visit_type_Foo_fields() · 65551903
      Eric Blake 提交于
      We were passing 'Foo **obj' to the internal helper function, but
      all uses within the helper were via reads of '*obj'.  Refactor
      things to pass one less level of indirection, by having the
      callers dereference before calling.
      
      For an example of the generated code change:
      
      |-static void visit_type_BalloonInfo_fields(Visitor *v, BalloonInfo **obj, Error **errp)
      |+static void visit_type_BalloonInfo_fields(Visitor *v, BalloonInfo *obj, Error **errp)
      | {
      |     Error *err = NULL;
      |
      |-    visit_type_int(v, "actual", &(*obj)->actual, &err);
      |+    visit_type_int(v, "actual", &obj->actual, &err);
      |     error_propagate(errp, err);
      | }
      |
      |@@ -261,7 +261,7 @@ void visit_type_BalloonInfo(Visitor *v,
      |     if (!*obj) {
      |         goto out_obj;
      |     }
      |-    visit_type_BalloonInfo_fields(v, obj, &err);
      |+    visit_type_BalloonInfo_fields(v, *obj, &err);
      | out_obj:
      
      The refactoring will also make it easier to reuse the helpers in
      a future patch when implicit structs are stored directly in the
      parent struct rather than boxed through a pointer.
      Signed-off-by: NEric Blake <eblake@redhat.com>
      Message-Id: <1455778109-6278-9-git-send-email-eblake@redhat.com>
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      65551903
    • M
      qapi-visit: Unify struct and union visit · 59d9e84c
      Markus Armbruster 提交于
      gen_visit_union() is now just like gen_visit_struct().  Rename
      it to gen_visit_object(), use it for structs, and drop
      gen_visit_struct().  Output is unchanged.
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      Message-Id: <1453902888-20457-4-git-send-email-armbru@redhat.com>
      [split out variant handling, rebase to earlier changes]
      Signed-off-by: NEric Blake <eblake@redhat.com>
      Message-Id: <1455778109-6278-8-git-send-email-eblake@redhat.com>
      59d9e84c
    • E
      qapi: Visit variants in visit_type_FOO_fields() · 9a5cd424
      Eric Blake 提交于
      We initially created the static visit_type_FOO_fields() helper
      function for reuse of code - we have cases where the initial
      setup for a visit has different allocation (depending on whether
      the fields represent a stand-alone type or are embedded as part
      of a larger type), but where the actual field visits are
      identical once a pointer is available.
      
      Up until the previous patch, visit_type_FOO_fields() was only
      used for structs (no variants), so it was covering every field
      for each type where it was emitted.
      
      Meanwhile, the code for visiting unions looks like:
      
      static visit_type_U_fields() {
          visit base;
          visit local_members;
      }
      visit_type_U() {
          visit_start_struct();
          visit_type_U_fields();
          visit variants;
          visit_end_struct();
      }
      
      which splits the fields of the union visit across two functions.
      Move the code to visit variants to live inside visit_type_U_fields(),
      while making it conditional on having variants so that all other
      instances of the helper function remain unchanged.  This is also
      a step closer towards unifying struct and union visits, and towards
      allowing one union type to be the branch of another flat union.
      
      The resulting diff to the generated code is a bit hard to read,
      but it can be verified that it touches only union types, and that
      the end result is the following general structure:
      
      static visit_type_U_fields() {
          visit base;
          visit local_members;
          visit variants;
      }
      visit_type_U() {
          visit_start_struct();
          visit_type_U_fields();
          visit_end_struct();
      }
      Signed-off-by: NEric Blake <eblake@redhat.com>
      Message-Id: <1455778109-6278-7-git-send-email-eblake@redhat.com>
      [gen_visit_struct_fields() parameter variants made mandatory]
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      9a5cd424
    • M
      qapi-visit: Simplify how we visit common union members · d7445b57
      Markus Armbruster 提交于
      For a simple union SU, gen_visit_union() generates a visit of its
      single tag member, like this:
      
          visit_type_SUKind(v, "type", &(*obj)->type, &err);
      
      For a flat union FU with base B, it generates a visit of its base
      fields:
      
          visit_type_B_fields(v, (B **)obj, &err);
      
      Instead, we can simply visit the common members using the same fields
      visit function we use for structs, generated with
      gen_visit_struct_fields().  This function visits the base if any, then
      the local members.
      
      For a simple union SU, visit_type_SU_fields() contains exactly the old
      tag member visit, because there is no base, and the tag member is the
      only member.  For instance, the code generated for qapi-schema.json's
      KeyValue changes like this:
      
          +static void visit_type_KeyValue_fields(Visitor *v, KeyValue **obj, Error **errp)
          +{
          +    Error *err = NULL;
          +
          +    visit_type_KeyValueKind(v, "type", &(*obj)->type, &err);
          +    if (err) {
          +        goto out;
          +    }
          +
          +out:
          +    error_propagate(errp, err);
          +}
          +
           void visit_type_KeyValue(Visitor *v, const char *name, KeyValue **obj, Error **errp)
           {
               Error *err = NULL;
          @@ -4863,7 +4911,7 @@ void visit_type_KeyValue(Visitor *v, con
               if (!*obj) {
                   goto out_obj;
               }
          -    visit_type_KeyValueKind(v, "type", &(*obj)->type, &err);
          +    visit_type_KeyValue_fields(v, obj, &err);
               if (err) {
                   goto out_obj;
               }
      
      For a flat union FU, visit_type_FU_fields() contains exactly the old
      base fields visit, because there is a base, but no members.  For
      instance, the code generated for qapi-schema.json's CpuInfo changes
      like this:
      
           static void visit_type_CpuInfoBase_fields(Visitor *v, CpuInfoBase **obj, Error **errp);
      
          +static void visit_type_CpuInfo_fields(Visitor *v, CpuInfo **obj, Error **errp)
          +{
          +    Error *err = NULL;
          +
          +    visit_type_CpuInfoBase_fields(v, (CpuInfoBase **)obj, &err);
          +    if (err) {
          +        goto out;
          +    }
          +
          +out:
          +    error_propagate(errp, err);
          +}
          +
           static void visit_type_CpuInfoX86_fields(Visitor *v, CpuInfoX86 **obj, Error **errp)
      ...
          @@ -3485,7 +3509,7 @@ void visit_type_CpuInfo(Visitor *v, cons
               if (!*obj) {
                   goto out_obj;
               }
          -    visit_type_CpuInfoBase_fields(v, (CpuInfoBase **)obj, &err);
          +    visit_type_CpuInfo_fields(v, obj, &err);
               if (err) {
                   goto out_obj;
               }
      
      As you see, the generated code grows a bit, but in practice, it's lost
      in the noise: qapi-schema.json's qapi-visit.c gains roughly 1%.
      
      This simplification became possible with commit 441cbac0 "qapi-visit:
      Convert to QAPISchemaVisitor, fixing bugs".  It's a step towards
      unifying gen_struct() and gen_union().
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      Message-Id: <1453902888-20457-2-git-send-email-armbru@redhat.com>
      [improve commit message examples]
      Signed-off-by: NEric Blake <eblake@redhat.com>
      Message-Id: <1455778109-6278-6-git-send-email-eblake@redhat.com>
      [Commit message tweaked]
      d7445b57
    • E
      qapi-visit: Honor prefix of discriminator enum · 9d3524b3
      Eric Blake 提交于
      When we added support for a user-specified prefix for an enum
      type (commit 351d36e4), we forgot to teach the qapi-visit code
      to honor that prefix in the case of using a prefixed enum as
      the discriminator for a flat union.  While there is still some
      on-list debate on whether we want to keep prefixes, we should
      at least make it work as long as it is still part of the code
      base.
      Reported-by: NDaniel P. Berrange <berrange@redhat.com>
      Signed-off-by: NEric Blake <eblake@redhat.com>
      Message-Id: <1455665965-27638-1-git-send-email-eblake@redhat.com>
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      9d3524b3
  4. 16 2月, 2016 1 次提交
  5. 09 2月, 2016 6 次提交
    • E
      qapi: Drop unused error argument for list and implicit struct · 08f9541d
      Eric Blake 提交于
      No backend was setting an error when ending the visit of a list or
      implicit struct, or when moving to the next list node.  Make the
      callers a bit easier to follow by making this a part of the contract,
      and removing the errp argument - callers can then unconditionally end
      an object as part of cleanup without having to think about whether a
      second error is dominated by a first, because there is no second
      error.
      
      A later patch will then tackle the larger task of splitting
      visit_end_struct(), which can indeed set an error.
      Signed-off-by: NEric Blake <eblake@redhat.com>
      Message-Id: <1454075341-13658-24-git-send-email-eblake@redhat.com>
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      08f9541d
    • E
      qapi: Drop unused 'kind' for struct/enum visit · 337283df
      Eric Blake 提交于
      visit_start_struct() and visit_type_enum() had a 'kind' argument
      that was usually set to either the stringized version of the
      corresponding qapi type name, or to NULL (although some clients
      didn't even get that right).  But nothing ever used the argument.
      It's even hard to argue that it would be useful in a debugger,
      as a stack backtrace also tells which type is being visited.
      
      Therefore, drop the 'kind' argument as dead.
      Signed-off-by: NEric Blake <eblake@redhat.com>
      Reviewed-by: NMarc-André Lureau <marcandre.lureau@redhat.com>
      Message-Id: <1454075341-13658-22-git-send-email-eblake@redhat.com>
      [Harmless rebase mistake cleaned up]
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      337283df
    • E
      qapi: Swap visit_* arguments for consistent 'name' placement · 51e72bc1
      Eric Blake 提交于
      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: NEric Blake <eblake@redhat.com>
      Reviewed-by: NMarc-André Lureau <marcandre.lureau@redhat.com>
      Message-Id: <1454075341-13658-19-git-send-email-eblake@redhat.com>
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      51e72bc1
    • E
      qapi: Don't cast Enum* to int* · 395a233f
      Eric Blake 提交于
      C compilers are allowed to represent enums as a smaller type
      than int, if all enum values fit in the smaller type.  There
      are even compiler flags that force the use of this smaller
      representation, although using them changes the ABI of a
      binary. Therefore, our generated code for visit_type_ENUM()
      (for all qapi enums) was wrong for casting Enum* to int* when
      calling visit_type_enum().
      
      It appears that no one has been using compiler ABI switches
      for qemu, because if they had, we are potentially dereferencing
      beyond bounds or even risking a SIGBUS on platforms where
      unaligned pointer dereferencing is fatal.  But it is still
      better to avoid the practice entirely, and just use the correct
      types.
      
      This matches the fix for alternate qapi types, done earlier in
      commit 0426d53c "qapi: Simplify visiting of alternate types",
      with generated code changing as:
      
      | void visit_type_QType(Visitor *v, QType *obj, const char *name, Error **errp)
      | {
      |-    visit_type_enum(v, (int *)obj, QType_lookup, "QType", name, errp);
      |+    int value = *obj;
      |+    visit_type_enum(v, &value, QType_lookup, "QType", name, errp);
      |+    *obj = value;
      | }
      Signed-off-by: NEric Blake <eblake@redhat.com>
      Reviewed-by: NMarc-André Lureau <marcandre.lureau@redhat.com>
      Message-Id: <1454075341-13658-17-git-send-email-eblake@redhat.com>
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      395a233f
    • E
      qapi-visit: Kill unused visit_end_union() · 7c91aabd
      Eric Blake 提交于
      The generated code can call visit_end_union() without having called
      visit_start_union().  Example:
      
              if (!*obj) {
                  goto out_obj;
              }
              visit_type_CpuInfoBase_fields(v, (CpuInfoBase **)obj, &err);
              if (err) {
                  goto out_obj; // if we go from here...
              }
              if (!visit_start_union(v, !!(*obj)->u.data, &err) || err) {
                  goto out_obj;
              }
              switch ((*obj)->arch) {
          [...]
              }
          out_obj:
              // ... then *obj is true, and ...
              error_propagate(errp, err);
              err = NULL;
              if (*obj) {
                  // we end up here
                  visit_end_union(v, !!(*obj)->u.data, &err);
              }
              error_propagate(errp, err);
      
      Harmless only because no visitor implements end_union().  Clean it up
      anyway, by deleting the function as useless.
      
      Messed up since we have visit_end_union (commit cee2dedb).
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      Message-Id: <1453902888-20457-3-git-send-email-armbru@redhat.com>
      [expand scope of patch to delete rather than repair]
      Signed-off-by: NEric Blake <eblake@redhat.com>
      Message-Id: <1454075341-13658-13-git-send-email-eblake@redhat.com>
      7c91aabd
    • E
      qapi: Track all failures between visit_start/stop · 92b09bab
      Eric Blake 提交于
      Inside the generated code between visit_start_struct() and
      visit_end_struct(), we were blindly setting the error into
      the caller's errp parameter.  But a future patch to split
      visit_end_struct() will require that we take action based
      on whether an error has occurred, which requires us to track
      all actions through a local err.  Rewrite the visits to be
      more in line with the other generated calls.
      
      Generated code changes look like:
      
      |     visit_start_struct(v, (void **)obj, "Abort", name, sizeof(Abort), &err);
      |-    if (!err) {
      |-        if (*obj) {
      |-            visit_type_Abort_fields(v, obj, errp);
      |-        }
      |-        visit_end_struct(v, &err);
      |+    if (err) {
      |+        goto out;
      |     }
      |+    if (!*obj) {
      |+        goto out_obj;
      |+    }
      |+    visit_type_Abort_fields(v, obj, &err);
      |+    error_propagate(errp, err);
      |+    err = NULL;
      |+out_obj:
      |+    visit_end_struct(v, &err);
      |+out:
      |     error_propagate(errp, err);
      | }
      Signed-off-by: NEric Blake <eblake@redhat.com>
      Message-Id: <1454075341-13658-12-git-send-email-eblake@redhat.com>
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      92b09bab
  6. 17 12月, 2015 4 次提交
    • E
      qapi: Fix alternates that accept 'number' but not 'int' · d00341af
      Eric Blake 提交于
      The QMP input visitor allows integral values to be assigned by
      promotion to a QTYPE_QFLOAT.  However, when parsing an alternate,
      we did not take this into account, such that an alternate that
      accepts 'number' and some other type, but not 'int', would reject
      integral values.
      
      With this patch, we now have the following desirable table:
      
          alternate has      case selected for
          'int'  'number'    QTYPE_QINT  QTYPE_QFLOAT
            no        no     error       error
            no       yes     'number'    'number'
           yes        no     'int'       error
           yes       yes     'int'       'number'
      
      While it is unlikely that we will ever use 'number' in an
      alternate other than in the testsuite, it never hurts to be
      more precise in what we allow.
      Signed-off-by: NEric Blake <eblake@redhat.com>
      Message-Id: <1449033659-25497-8-git-send-email-eblake@redhat.com>
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      d00341af
    • E
      qapi: Simplify visiting of alternate types · 0426d53c
      Eric Blake 提交于
      Previously, working with alternates required two lookup arrays
      and some indirection: for type Foo, we created Foo_qtypes[]
      which maps each qtype to a value of the generated FooKind enum,
      then look up that value in FooKind_lookup[] like we do for other
      union types.
      
      This has a couple of subtle bugs.  First, the generator was
      creating a call with a parameter '(int *) &(*obj)->type' where
      type is an enum type; this is unsafe if the compiler chooses
      to store the enum type in a different size than int, where
      assigning through the wrong size pointer can corrupt data or
      cause a SIGBUS.
      
      Related bug, not not fixed in this patch: qapi-visit.py's
      gen_visit_enum() generates a cast of its enum * argument to
      int *. Marked FIXME.
      
      Second, since the values of the FooKind enum start at zero, all
      entries of the Foo_qtypes[] array that were not explicitly
      initialized will map to the same branch of the union as the
      first member of the alternate, rather than triggering a desired
      failure in visit_get_next_type().  Fortunately, the bug seldom
      bites; the very next thing the input visitor does is try to
      parse the incoming JSON with the wrong parser, which normally
      fails; the output visitor is not used with a C struct in that
      state, and the dealloc visitor has nothing to clean up (so
      there is no leak).
      
      However, the second bug IS observable in one case: parsing an
      integer causes unusual behavior in an alternate that contains
      at least a 'number' member but no 'int' member, because the
      'number' parser accepts QTYPE_QINT in addition to the expected
      QTYPE_QFLOAT (that is, since 'int' is not a member, the type
      QTYPE_QINT accidentally maps to FooKind 0; if this enum value
      is the 'number' branch the integer parses successfully, but if
      the 'number' branch is not first, some other branch tries to
      parse the integer and rejects it).  A later patch will worry
      about fixing alternates to always parse all inputs that a
      non-alternate 'number' would accept, for now this is still
      marked FIXME in the updated test-qmp-input-visitor.c, to
      merely point out that new undesired behavior of 'ans' matches
      the existing undesired behavior of 'asn'.
      
      This patch fixes the default-initialization bug by deleting the
      indirection, and modifying get_next_type() to directly assign a
      QTypeCode parameter.  This in turn fixes the type-casting bug,
      as we are no longer casting a pointer to enum to a questionable
      size. There is no longer a need to generate an implicit FooKind
      enum associated with the alternate type (since the QMP wire
      format never uses the stringized counterparts of the C union
      member names).  Since the updated visit_get_next_type() does not
      know which qtypes are expected, the generated visitor is
      modified to generate an error statement if an unexpected type is
      encountered.
      
      Callers now have to know the QTYPE_* mapping when looking at the
      discriminator; but so far, only the testsuite was even using the
      C struct of an alternate types.  I considered the possibility of
      keeping the internal enum FooKind, but initialized differently
      than most generated arrays, as in:
        typedef enum FooKind {
            FOO_KIND_A = QTYPE_QDICT,
            FOO_KIND_B = QTYPE_QINT,
        } FooKind;
      to create nicer aliases for knowing when to use foo->a or foo->b
      when inspecting foo->type; but it turned out to add too much
      complexity, especially without a client.
      
      There is a user-visible side effect to this change, but I
      consider it to be an improvement. Previously,
      the invalid QMP command:
        {"execute":"blockdev-add", "arguments":{"options":
          {"driver":"raw", "id":"a", "file":true}}}
      failed with:
        {"error": {"class": "GenericError",
          "desc": "Invalid parameter type for 'file', expected: QDict"}}
      (visit_get_next_type() succeeded, and the error comes from the
      visit_type_BlockdevOptions() expecting {}; there is no mention of
      the fact that a string would also work).  Now it fails with:
        {"error": {"class": "GenericError",
          "desc": "Invalid parameter type for 'file', expected: BlockdevRef"}}
      (the error when the next type doesn't match any expected types for
      the overall alternate).
      Signed-off-by: NEric Blake <eblake@redhat.com>
      Message-Id: <1449033659-25497-5-git-send-email-eblake@redhat.com>
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      0426d53c
    • E
      qapi: Convert QType into QAPI built-in enum type · 7264f5c5
      Eric Blake 提交于
      What's more meta than using qapi to define qapi? :)
      
      Convert QType into a full-fledged[*] builtin qapi enum type, so
      that a subsequent patch can then use it as the discriminator
      type of qapi alternate types.  Fortunately, the judicious use of
      'prefix' in the qapi definition avoids churn to the spelling of
      the enum constants.
      
      To avoid circular definitions, we have to flip the order of
      inclusion between "qobject.h" vs. "qapi-types.h".  Back in commit
      28770e05, we had the latter include the former, so that we could
      use 'QObject *' for our implementation of 'any'.  But that usage
      also works with only a forward declaration, whereas the
      definition of QObject requires QType to be a complete type.
      
      [*] The type has to be builtin, rather than declared in
      qapi/common.json, because we want to use it for alternates even
      when common.json is not included. But since it is the first
      builtin enum type, we have to add special cases to qapi-types
      and qapi-visit to only emit definitions once, even when two
      qapi files are being compiled into the same binary (the way we
      already handled builtin list types like 'intList').  We may
      need to revisit how multiple qapi files share common types,
      but that's a project for another day.
      Signed-off-by: NEric Blake <eblake@redhat.com>
      Message-Id: <1449033659-25497-4-git-send-email-eblake@redhat.com>
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      7264f5c5
    • E
      qapi: Track simple union tag in object.local_members · da34a9bd
      Eric Blake 提交于
      We were previously creating all unions with an empty list for
      local_members.  However, it will make it easier to unify struct
      and union generation if we include the generated tag member in
      local_members.  That way, we can have a common code pattern:
      visit the base (if any), visit the local members (if any), visit
      the variants (if any).  The local_members of a flat union
      remains empty (because the discriminator is already visited as
      part of the base).  Then, by visiting tag_member.check() during
      AlternateType.check(), we no longer need to call it during
      Variants.check().
      
      The various front end entities now exist as follows:
      struct: optional base, optional local_members, no variants
      simple union: no base, one-element local_members, variants with tag_member
        from local_members
      flat union: base, no local_members, variants with tag_member from base
      alternate: no base, no local_members, variants
      
      With the new local members, we require a bit of finesse to
      avoid assertions in the clients.
      
      No change to generated code.
      Signed-off-by: NEric Blake <eblake@redhat.com>
      Message-Id: <1447836791-369-2-git-send-email-eblake@redhat.com>
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      da34a9bd
  7. 10 11月, 2015 1 次提交
    • E
      qapi: Test failure in middle of array parse · dd5ee2c2
      Eric Blake 提交于
      Our generated list visitors have the same problem as has been
      mentioned elsewhere (see commit 2f52e205): they allocate data
      even on failure. An upcoming patch will correct things to
      provide saner guarantees, but first we need to expose the
      behavior in the testsuite to ensure we aren't introducing any
      memory usage bugs.
      
      There are more test cases throughout the test-qmp-input-* tests
      that already deal with partial allocation; a later commit will
      clean up all visit_type_FOO(), without marking all of the tests
      with FIXME at this time.
      Signed-off-by: NEric Blake <eblake@redhat.com>
      Message-Id: <1446791754-23823-10-git-send-email-eblake@redhat.com>
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      dd5ee2c2
  8. 02 11月, 2015 5 次提交
    • E
      qapi-visit: Convert to new qapi union layout · 150d0564
      Eric Blake 提交于
      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.
      
      Make the conversion to the new layout for qapi-visit.py.
      
      Generated code changes look like:
      
      |@@ -4912,16 +4912,16 @@ void visit_type_MemoryDeviceInfo(Visitor
      |     if (!*obj) {
      |         goto out_obj;
      |     }
      |-    visit_type_MemoryDeviceInfoKind(v, &(*obj)->kind, "type", &err);
      |+    visit_type_MemoryDeviceInfoKind(v, &(*obj)->type, "type", &err);
      |     if (err) {
      |         goto out_obj;
      |     }
      |-    if (!visit_start_union(v, !!(*obj)->data, &err) || err) {
      |+    if (!visit_start_union(v, !!(*obj)->u.data, &err) || err) {
      |         goto out_obj;
      |     }
      |-    switch ((*obj)->kind) {
      |+    switch ((*obj)->type) {
      |     case MEMORY_DEVICE_INFO_KIND_DIMM:
      |-        visit_type_PCDIMMDeviceInfo(v, &(*obj)->dimm, "data", &err);
      |+        visit_type_PCDIMMDeviceInfo(v, &(*obj)->u.dimm, "data", &err);
      |         break;
      |     default:
      |         abort();
      |@@ -4930,7 +4930,7 @@ out_obj:
      |     error_propagate(errp, err);
      |     err = NULL;
      |     if (*obj) {
      |-        visit_end_union(v, !!(*obj)->data, &err);
      |+        visit_end_union(v, !!(*obj)->u.data, &err);
      |     }
      |     error_propagate(errp, err);
      |     err = NULL;
      Signed-off-by: NEric Blake <eblake@redhat.com>
      Message-Id: <1445898903-12082-14-git-send-email-eblake@redhat.com>
      [Commit message tweaked slightly]
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      150d0564
    • E
      qapi-visit: Remove redundant functions for flat union base · 5c5e51a0
      Eric Blake 提交于
      The code for visiting the base class of a child struct created
      visit_type_Base_fields() which covers all fields of Base; while
      the code for visiting the base class of a flat union created
      visit_type_Union_fields() covering all fields of the base
      except the discriminator.  But since the base class includes
      the discriminator of a flat union, we can just visit the entire
      base, without needing a separate visit of the discriminator.
      Not only is consistently visiting all fields easier to
      understand, it lets us share code.
      
      The generated code in qapi-visit.c loses several now-unused
      visit_type_UNION_fields(), along with changes like:
      
      |@@ -1654,11 +1557,7 @@ void visit_type_BlockdevOptions(Visitor
      |     if (!*obj) {
      |         goto out_obj;
      |     }
      |-    visit_type_BlockdevOptions_fields(v, obj, &err);
      |-    if (err) {
      |-        goto out_obj;
      |-    }
      |-    visit_type_BlockdevDriver(v, &(*obj)->driver, "driver", &err);
      |+    visit_type_BlockdevOptionsBase_fields(v, (BlockdevOptionsBase **)obj, &err);
      |     if (err) {
      |         goto out_obj;
      |     }
      
      and forward declarations where needed.  Note that the cast of obj
      to BASE ** is necessary to call visit_type_BASE_fields() (and we
      can't use our upcast wrappers, because those work on pointers while
      we have a pointer-to-pointer).
      Signed-off-by: NEric Blake <eblake@redhat.com>
      Message-Id: <1445898903-12082-12-git-send-email-eblake@redhat.com>
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      5c5e51a0
    • E
      qapi: Unbox base members · ddf21908
      Eric Blake 提交于
      Rather than storing a base class as a pointer to a box, just
      store the fields of that base class in the same order, so that
      a child struct can be directly cast to its parent.  This gives
      less malloc overhead, less pointer dereferencing, and even less
      generated code.  Compare to the earlier commit 1e6c1616 "qapi:
      Generate a nicer struct for flat unions" (although that patch
      had fewer places to change, as less of qemu was directly using
      qapi structs for flat unions).  It also allows us to turn on
      automatic type-safe wrappers for upcasting to the base class
      of a struct.
      
      Changes to the generated code look like this in qapi-types.h:
      
      | struct SpiceChannel {
      |-    SpiceBasicInfo *base;
      |+    /* Members inherited from SpiceBasicInfo: */
      |+    char *host;
      |+    char *port;
      |+    NetworkAddressFamily family;
      |+    /* Own members: */
      |     int64_t connection_id;
      
      as well as additional upcast functions like qapi_SpiceChannel_base().
      Meanwhile, changes to qapi-visit.c look like:
      
      | static void visit_type_SpiceChannel_fields(Visitor *v, SpiceChannel **obj, Error **errp)
      | {
      |     Error *err = NULL;
      |
      |-    visit_type_implicit_SpiceBasicInfo(v, &(*obj)->base, &err);
      |+    visit_type_SpiceBasicInfo_fields(v, (SpiceBasicInfo **)obj, &err);
      |     if (err) {
      
      (the cast is necessary, since our upcast wrappers only deal with a
      single pointer, not pointer-to-pointer); plus the wholesale
      elimination of some now-unused visit_type_implicit_FOO() functions.
      
      Without boxing, the corner case of one empty struct having
      another empty struct as its base type now requires inserting a
      dummy member (previously, the 'Base *base' member sufficed).
      
      And now that we no longer consume a 'base' member in the generated
      C struct, we can delete the former negative struct-base-clash-base
      test.
      Signed-off-by: NEric Blake <eblake@redhat.com>
      Message-Id: <1445898903-12082-11-git-send-email-eblake@redhat.com>
      [Commit message tweaked slightly]
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      ddf21908
    • E
      qapi-visit: Split off visit_type_FOO_fields forward decl · d02cf377
      Eric Blake 提交于
      We generate a static visit_type_FOO_fields() for every type
      FOO.  However, sometimes we need a forward declaration. Split
      the code to generate the forward declaration out of
      gen_visit_implicit_struct() into a new gen_visit_fields_decl(),
      and also prepare for a forward declaration to be emitted
      during gen_visit_struct(), so that a future patch can switch
      from using visit_type_FOO_implicit() to the simpler
      visit_type_FOO_fields() as part of unboxing the base class
      of a struct.
      
      No change to generated code.
      Signed-off-by: NEric Blake <eblake@redhat.com>
      Message-Id: <1445898903-12082-8-git-send-email-eblake@redhat.com>
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      d02cf377
    • E
      qapi: More robust conditions for when labels are needed · f9e6102b
      Eric Blake 提交于
      We were using regular expressions to see if ret included
      any earlier text that emitted a 'goto out;' line, to decide
      whether we needed to output an 'out:' label.  But this is
      fragile, if the ret text can possibly combine more than one
      generated function body, where the first function used a
      goto but the second does not.  Change the code to just check
      for the known conditions which cause an error check to be
      needed.  Besides, it's slightly more efficient to use plain
      checks than regular expression searching.
      
      No change to generated code.
      Signed-off-by: NEric Blake <eblake@redhat.com>
      Message-Id: <1445898903-12082-4-git-send-email-eblake@redhat.com>
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      f9e6102b
  9. 15 10月, 2015 3 次提交
    • E
      qapi: Don't use info as witness of implicit object type · 49823c4b
      Eric Blake 提交于
      A future patch will enable error reporting from the various
      QAPISchema*.check() methods.  But to report an error related
      to an implicit type, we'll need to associate a location with
      the type (the same location as the top-level entity that is
      causing the creation of the implicit type), and once we do
      that, keying off of whether foo.info exists is no longer a
      viable way to determine if foo is an implicit type.
      
      Instead, add an is_implicit() method to QAPISchemaEntity, and use it.
      It can be overridden later for ObjectType and EnumType, when implicit
      instances of those classes gain info.
      Signed-off-by: NEric Blake <eblake@redhat.com>
      Message-Id: <1444710158-8723-8-git-send-email-eblake@redhat.com>
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      49823c4b
    • E
      qapi: Use predicate callback to determine visit filtering · 25a0d9c9
      Eric Blake 提交于
      Previously, qapi-types and qapi-visit filtered out implicit
      objects during visit_object_type() by using 'info' (works since
      implicit objects do not [yet] have associated info); meanwhile
      qapi-introspect filtered out all schema types on the first pass
      by returning a python type from visit_begin(), which was then
      used at a distance in QAPISchema.visit() to do the filtering.
      
      Rather than keeping these ad hoc approaches, add a new visitor
      callback visit_needed() which returns False to skip a given
      entity, and which defaults to True unless overridden.  Use the
      new mechanism to simplify all three filtering visitors.
      
      No change to the generated code.
      Suggested-by: NMarkus Armbruster <armbru@redhat.com>
      Signed-off-by: NEric Blake <eblake@redhat.com>
      Message-Id: <1444710158-8723-2-git-send-email-eblake@redhat.com>
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      25a0d9c9
    • E
      qapi: Fix regression with '-netdev help' · d08ac81a
      Eric Blake 提交于
      Commit e36c714e causes 'qemu -netdev help' to dump core, because the
      call to visit_end_union() is no longer conditional on whether *obj was
      allocated.
      
      Reported by Marc-André Lureau <marcandre.lureau@gmail.com>
      Signed-off-by: NEric Blake <eblake@redhat.com>
      Message-Id: <1444861825-19256-1-git-send-email-eblake@redhat.com>
      [Commit message tweaked to say 'help' instead of '?']
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      d08ac81a
  10. 13 10月, 2015 4 次提交
    • E
      qapi: Share gen_visit_fields() · 82ca8e46
      Eric Blake 提交于
      Consolidate the code between visit, command marshalling, and
      event generation that iterates over the members of a struct.
      It reduces code duplication in the generator, so that a future
      patch can reduce the size of generated code while touching only
      one instead of three locations.
      
      There are no changes to the generated marshal code.
      
      The visitor code becomes slightly more verbose, but remains
      semantically equivalent, and is actually easier to read as
      it follows a more common idiom:
      
      |     visit_optional(v, &(*obj)->has_device, "device", &err);
      |-    if (!err && (*obj)->has_device) {
      |-        visit_type_str(v, &(*obj)->device, "device", &err);
      |-    }
      |     if (err) {
      |         goto out;
      |     }
      |+    if ((*obj)->has_device) {
      |+        visit_type_str(v, &(*obj)->device, "device", &err);
      |+        if (err) {
      |+            goto out;
      |+        }
      |+    }
      
      The event code becomes slightly more verbose, but this is
      arguably a bug fix: although the visitors are not well
      documented, use of an optional member should not be attempted
      unless guarded by a prior call to visit_optional().  Works only
      because the output qmp visitor has a no-op visit_optional():
      
      |+    visit_optional(v, &has_offset, "offset", &err);
      |+    if (err) {
      |+        goto out;
      |+    }
      |     if (has_offset) {
      |         visit_type_int(v, &offset, "offset", &err);
      Signed-off-by: NEric Blake <eblake@redhat.com>
      Message-Id: <1443565276-4535-17-git-send-email-eblake@redhat.com>
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      82ca8e46
    • E
      qapi: Share gen_err_check() · 1f353344
      Eric Blake 提交于
      qapi-commands has a nice helper gen_err_check(), but did not
      use it everywhere. In fact, using it in more places makes it
      easier to reduce the lines of code used for generating error
      checks.  This in turn will make it easier for later patches
      to consolidate another common pattern among the generators.
      
      The generated code has fewer blank lines in qapi-event.c functions,
      but has no semantic difference.
      Signed-off-by: NEric Blake <eblake@redhat.com>
      Message-Id: <1443565276-4535-16-git-send-email-eblake@redhat.com>
      [Drop another blank line for symmetry]
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      1f353344
    • E
      qapi: Consistent generated code: minimize push_indent() usage · 05372f70
      Eric Blake 提交于
      We had some pointless differences in the generated code for visit,
      command marshalling, and events; unifying them makes it easier for
      future patches to consolidate to common helper functions.
      This is one patch of a series to clean up these differences.
      
      This patch reduces the number of push_indent()/pop_indent() pairs
      so that generated code is typically already at its natural output
      indentation in the python files.  It is easier to reason about
      generated code if the reader does not have to track how much
      spacing will be inserted alongside the code, and moreso when all
      of the generators use the same patterns (qapi-type and qapi-event
      were already using in-place indentation).
      
      Arguably, the resulting python may be a bit harder to read with C
      code at the same indentation as python; on the other hand, not
      having to think about push_indent() is a win, and most decent
      editors provide syntax highlighting that makes it easier to
      visually distinguish python code from string literals that will
      become C code.
      
      There is no change to the generated output.
      Signed-off-by: NEric Blake <eblake@redhat.com>
      Message-Id: <1443565276-4535-15-git-send-email-eblake@redhat.com>
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      05372f70
    • E
      qapi: Consistent generated code: prefer common indentation · e36c714e
      Eric Blake 提交于
      We had some pointless differences in the generated code for visit,
      command marshalling, and events; unifying them makes it easier for
      future patches to consolidate to common helper functions.
      This is one patch of a series to clean up these differences.
      
      This patch adjusts gen_visit_union() to use the same indentation
      as other functions, namely, by jumping early to the error label
      if the object was not set rather than placing the rest of the
      body inside an if for when it is set.
      
      No change in semantics to the generated code.
      Signed-off-by: NEric Blake <eblake@redhat.com>
      Message-Id: <1443565276-4535-14-git-send-email-eblake@redhat.com>
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      e36c714e