1. 05 3月, 2016 1 次提交
  2. 19 2月, 2016 4 次提交
    • 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: Emit structs used as variants in topological order · 1de5d4ca
      Eric Blake 提交于
      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: NEric Blake <eblake@redhat.com>
      Message-Id: <1455778109-6278-11-git-send-email-eblake@redhat.com>
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      1de5d4ca
    • 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
  3. 16 2月, 2016 1 次提交
  4. 09 2月, 2016 1 次提交
    • 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
  5. 17 12月, 2015 6 次提交
    • E
      qapi-types: Drop unnedeed ._fwdefn · 0b2e84ba
      Eric Blake 提交于
      Previously, the generated code in qapi-types.c initialized all
      enum lookup tables first, prior to any other definitions.  But
      there are no topological sorting requirements that mandate this
      layout, so we can drop the QAPISchemaGenTypeVisitor._fwdefn
      field and just generate all definitions in visitation order.
      
      The generated code shows some churn due to reordering, but it
      is still fairly straightforward to follow (all the deletions
      occur in one hunk, and all the deleted lines are re-inserted
      in the same order later in the same files, just spread across
      multiple insertion points).
      Suggested-by: NMarkus Armbruster <armbru@redhat.com>
      Signed-off-by: NEric Blake <eblake@redhat.com>
      Message-Id: <1449033659-25497-6-git-send-email-eblake@redhat.com>
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      0b2e84ba
    • 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-types: Simplify gen_struct_field[s] · 7d9586f9
      Eric Blake 提交于
      Simplify gen_struct_fields() back to a single iteration over a
      list of fields (like it was prior to commit f87ab7f9), by moving
      the generated comments to gen_object().  Then, inline
      gen_struct_field() into its only caller.
      Signed-off-by: NEric Blake <eblake@redhat.com>
      Message-Id: <1447836791-369-4-git-send-email-eblake@redhat.com>
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      7d9586f9
    • E
      qapi-types: Consolidate gen_struct() and gen_union() · 570cd8d1
      Eric Blake 提交于
      These two methods are now close enough that we can finally merge
      them, relying on the fact that simple unions now provide a
      reasonable local_members.  Change gen_struct() to gen_object()
      that handles all forms of QAPISchemaObjectType, and rename and
      shrink gen_union() to gen_variants() to handle the portion of
      gen_object() needed when variants are present.
      
      gen_struct_fields() now has a single caller, so it no longer
      needs an optional parameter; however, I did not choose to inline
      it into the caller.
      
      No difference to generated code.
      Signed-off-by: NEric Blake <eblake@redhat.com>
      Message-Id: <1447836791-369-3-git-send-email-eblake@redhat.com>
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      570cd8d1
    • 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
  6. 02 11月, 2015 6 次提交
    • E
      qapi: Simplify gen_struct_field() · 32bc6879
      Eric Blake 提交于
      Rather than having all callers pass a name, type, and optional
      flag, have them instead pass a QAPISchemaObjectTypeMember which
      already has all that information.
      
      No change to generated code.
      Signed-off-by: NEric Blake <eblake@redhat.com>
      Message-Id: <1445898903-12082-25-git-send-email-eblake@redhat.com>
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      32bc6879
    • E
      qapi: Finish converting to new qapi union layout · e4ba22b3
      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.
      
      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 4dc2e690), 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: NEric Blake <eblake@redhat.com>
      Message-Id: <1445898903-12082-23-git-send-email-eblake@redhat.com>
      [Commit message tweaked]
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      e4ba22b3
    • E
      qapi: Start converting to new qapi union layout · f51d8fab
      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.
      
      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 4dc2e690), 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: NEric Blake <eblake@redhat.com>
      Message-Id: <1445898903-12082-13-git-send-email-eblake@redhat.com>
      [Commit message tweaked slightly]
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      f51d8fab
    • 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: Prefer typesafe upcasts to qapi base classes · 30594fe1
      Eric Blake 提交于
      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: NEric Blake <eblake@redhat.com>
      Message-Id: <1445898903-12082-10-git-send-email-eblake@redhat.com>
      [Commit message tweaked]
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      30594fe1
    • E
      qapi-types: Refactor base fields output · f87ab7f9
      Eric Blake 提交于
      Move code from gen_union() into gen_struct_fields() in order for
      a later patch to share code when enumerating inherited fields
      for struct types.
      
      No change to generated code.
      Signed-off-by: NEric Blake <eblake@redhat.com>
      Message-Id: <1445898903-12082-9-git-send-email-eblake@redhat.com>
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      f87ab7f9
  7. 15 10月, 2015 2 次提交
    • 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
  8. 13 10月, 2015 1 次提交
    • E
      qapi: Consistent generated code: prefer visitor 'v' · f8b7f1a8
      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 names the local visitor variable 'v' rather than 'm'.
      Related objects, such as 'QapiDeallocVisitor', are also named by
      their initials instead of an unrelated leading m.
      
      No change in semantics to the generated code.
      Signed-off-by: NEric Blake <eblake@redhat.com>
      Message-Id: <1443565276-4535-12-git-send-email-eblake@redhat.com>
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      f8b7f1a8
  9. 21 9月, 2015 5 次提交
    • M
      qapi: Introduce a first class 'any' type · 28770e05
      Markus Armbruster 提交于
      It's first class, because unlike '**', it actually works, i.e. doesn't
      require 'gen': false.
      
      '**' will go away next.
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      Reviewed-by: NEric Blake <eblake@redhat.com>
      Reviewed-by: NDaniel P. Berrange <berrange@redhat.com>
      28770e05
    • M
      qapi: Clean up after recent conversions to QAPISchemaVisitor · e98859a9
      Markus Armbruster 提交于
      Generate just 'FOO' instead of 'struct FOO' when possible.
      
      Drop helper functions that are now unused.
      
      Make pep8 and pylint reasonably happy.
      
      Rename generate_FOO() functions to gen_FOO() for consistency.
      
      Use more consistent and sensible variable names.
      
      Consistently use c_ for mapping keys when their value is a C
      identifier or type.
      
      Simplify gen_enum() and gen_visit_union()
      
      Consistently use single quotes for C text string literals.
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      Message-Id: <1442401589-24189-14-git-send-email-armbru@redhat.com>
      Reviewed-by: NDaniel P. Berrange <berrange@redhat.com>
      Reviewed-by: NEric Blake <eblake@redhat.com>
      e98859a9
    • M
      qapi: De-duplicate enum code generation · efd2eaa6
      Markus Armbruster 提交于
      Duplicated in commit 21cd70df.  Yes, we can't import qapi-types, but
      that's no excuse.  Move the helpers from qapi-types.py to qapi.py, and
      replace the duplicates in qapi-event.py.
      
      The generated event enumeration type's lookup table becomes
      const-correct (see commit 2e4450ff), and uses explicit indexes instead
      of relying on order (see commit 912ae9c8).
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      Message-Id: <1442401589-24189-10-git-send-email-armbru@redhat.com>
      Reviewed-by: NDaniel P. Berrange <berrange@redhat.com>
      Reviewed-by: NEric Blake <eblake@redhat.com>
      efd2eaa6
    • M
      qapi-types: Convert to QAPISchemaVisitor, fixing flat unions · 2b162ccb
      Markus Armbruster 提交于
      Fixes flat unions to get the base's base members.  Test case is from
      commit 2fc00432, 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: NMarkus Armbruster <armbru@redhat.com>
      Reviewed-by: NDaniel P. Berrange <berrange@redhat.com>
      Reviewed-by: NEric Blake <eblake@redhat.com>
      2b162ccb
    • M
      qapi: New QAPISchema intermediate reperesentation · ac88219a
      Markus Armbruster 提交于
      The QAPI code generators work with a syntax tree (nested dictionaries)
      plus a few symbol tables (also dictionaries) on the side.
      
      They have clearly outgrown these simple data structures.  There's lots
      of rummaging around in dictionaries, and information is recomputed on
      the fly.  For the work I'm going to do, I want more clearly defined
      and more convenient interfaces.
      
      Going forward, I also want less coupling between the back-ends and the
      syntax tree, to make messing with the syntax easier.
      
      Create a bunch of classes to represent QAPI schemata.
      
      Have the QAPISchema initializer call the parser, then walk the syntax
      tree to create the new internal representation, and finally perform
      semantic analysis.
      
      Shortcut: the semantic analysis still relies on existing check_exprs()
      to do the actual semantic checking.  All this code needs to move into
      the classes.  Mark as TODO.
      
      Simple unions are lowered to flat unions.  Flat unions and structs are
      represented as a more general object type.
      
      Catching name collisions in generated code would be nice.  Mark as
      TODO.
      
      We generate array types eagerly, even though most of them aren't used.
      Mark as TODO.
      
      Nothing uses the new intermediate representation just yet, thus no
      change to generated files.
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      Reviewed-by: NDaniel P. Berrange <berrange@redhat.com>
      Reviewed-by: NEric Blake <eblake@redhat.com>
      ac88219a
  10. 15 9月, 2015 1 次提交
    • D
      qapi: allow override of default enum prefix naming · 351d36e4
      Daniel P. Berrange 提交于
      The camel_to_upper() method applies some heuristics to turn
      a mixed case type name into an all-uppercase name. This is
      used for example, to generate enum constant name prefixes.
      
      The heuristics don't also generate a satisfactory name
      though. eg
      
        { 'enum': 'QCryptoTLSCredsEndpoint',
          'data': ['client', 'server']}
      
      Results in Q_CRYPTOTLS_CREDS_ENDPOINT_CLIENT. This has
      an undesirable _ after the initial Q and is missing an
      _ between the CRYPTO & TLS strings.
      
      Rather than try to add more and more heuristics to try
      to cope with this, simply allow the QAPI schema to
      specify the desired enum constant prefix explicitly.
      
      eg
      
        { 'enum': 'QCryptoTLSCredsEndpoint',
          'prefix': 'QCRYPTO_TLS_CREDS_ENDPOINT',
          'data': ['client', 'server']}
      
      Now gives the QCRYPTO_TLS_CREDS_ENDPOINT_CLIENT name.
      Signed-off-by: NDaniel P. Berrange <berrange@redhat.com>
      351d36e4
  11. 04 9月, 2015 5 次提交
    • M
      qapi: Generated code cleanup · 3a864e7c
      Markus Armbruster 提交于
      Clean up white-space, brace placement, and superfluous #ifdef
      QAPI_TYPES_BUILTIN_CLEANUP_DEF.
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      Reviewed-by: NEric Blake <eblake@redhat.com>
      3a864e7c
    • E
      qapi: Document shortcoming with union 'data' branch · ca56a822
      Eric Blake 提交于
      Add a FIXME to remind us to fully audit whether removing the
      'void *data' branch of each qapi union type can be done safely.
      Signed-off-by: NEric Blake <eblake@redhat.com>
      Message-Id: <1438297637-26789-1-git-send-email-eblake@redhat.com>
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      ca56a822
    • M
      qapi: Generate a nicer struct for flat unions · 1e6c1616
      Markus Armbruster 提交于
      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: NMarkus Armbruster <armbru@redhat.com>
      Reviewed-by: NEric Blake <eblake@redhat.com>
      1e6c1616
    • M
      qapi: Fix generated code when flat union has member 'kind' · 0f61af3e
      Markus Armbruster 提交于
      A flat union's tag member gets renamed to 'kind' in the generated
      code.  Breaks when another member named 'kind' exists.
      
      Example, adapted from qapi-schema-test.json:
      
          { 'struct': 'UserDefUnionBase',
            'data': { 'kind': 'str', 'enum1': 'EnumOne' } }
      
      We generate:
      
          struct UserDefFlatUnion
          {
              EnumOne kind;
              union {
                  void *data;
                  UserDefA *value1;
                  UserDefB *value2;
                  UserDefB *value3;
              };
              char *kind;
          };
      
      Kill the silly rename.
      Reported-by: NEric Blake <eblake@redhat.com>
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      Reviewed-by: NEric Blake <eblake@redhat.com>
      0f61af3e
    • M
      qapi: Drop unused and useless parameters and variables · 5aa05d3f
      Markus Armbruster 提交于
      gen_sync_call()'s parameter indent is useless: gen_sync_call() uses it
      only as optional argument for push_indent() and pop_indent(), their
      default is four, and gen_sync_call()'s only caller passes four.  Drop
      the parameter.
      
      gen_visitor_input_containers_decl()'s parameter obj is always
      "QOBJECT(args)".  Use that, and drop the parameter.
      
      Drop unused parameters of gen_marshal_output(),
      gen_marshal_input_decl(), generate_visit_struct_body(),
      generate_visit_list(), generate_visit_enum(), generate_declaration(),
      generate_enum_declaration(), generate_decl_enum().
      
      Drop unused variables in generate_event_enum_lookup(),
      generate_enum_lookup(), generate_visit_struct_fields(), check_event().
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      Reviewed-by: NEric Blake <eblake@redhat.com>
      5aa05d3f
  12. 20 6月, 2015 1 次提交
  13. 18 6月, 2015 4 次提交
  14. 15 5月, 2015 2 次提交