
Commit ac88219a had several TODO markers about whether we needed to automatically create the corresponding array type alongside any other type. It turns out that most of the time, we don't! There are a few exceptions: 1) We have a few situations where we use an array type in internal code but do not expose that type through QMP; fix it by declaring a dummy type that forces the generator to see that we want to use the array type. 2) The builtin arrays (such as intList for QAPI ['int']) must always be generated, because of the way our QAPI_TYPES_BUILTIN compile guard works: we have situations (at the very least tests/test-qmp-output-visitor.c) that include both top-level "qapi-types.h" (via "error.h") and a secondary "test-qapi-types.h". If we were to only emit the builtin types when used locally, then the first .h file would not include all types, but the second .h does not declare anything at all because the first .h set QAPI_TYPES_BUILTIN, and we would end up with compilation error due to things like unknown type 'int8List'. Actually, we may need to revisit how we do type guards, and change from a single QAPI_TYPES_BUILTIN over to a different usage pattern that does one #ifdef per qapi type - right now, the only types that are declared multiple times between two qapi .json files for inclusion by a single .c file happen to be the builtin arrays. But now that we have QAPI 'include' statements, it is logical to assume that we will soon reach a point where we want to reuse non-builtin types (yes, I'm thinking about what it will take to add introspection to QGA, where we will want to reuse the SchemaInfo type and friends). One #ifdef per type will help ensure that generating the same qapi type into more than one qapi-types.h won't cause collisions when both are included in the same .c file; but we also have to solve how to avoid creating duplicate qapi-types.c entry points. So that is a problem left for another day. Generated code for qapi-types and qapi-visit is drastically reduced; less than a third of the arrays that were blindly created were actually needed (a quick grep shows we dropped from 219 to 69 *List types), and the .o files lost more than 30% of their bulk. [For best results, diff the generated files with 'git diff --patience --no-index pre post'.] Interestingly, the introspection output is unchanged - this is because we already cull all types that are not indirectly reachable from a command or event, so introspection was already using only a subset of array types. The subset of types introspected is now a much larger percentage of the overall set of array types emitted in qapi-types.h (since the larger set shrunk), but still not 100% (evidence that the array types emitted for our new Dummy structs, and the new struct itself, don't affect QMP). Signed-off-by: Eric Blake <eblake@redhat.com> Message-Id: <1444710158-8723-9-git-send-email-eblake@redhat.com> [Moved array info tracking to a later patch] Signed-off-by: Markus Armbruster <armbru@redhat.com>
200 lines
6.6 KiB
Plaintext
200 lines
6.6 KiB
Plaintext
object :empty
|
|
object :obj-EVENT_C-arg
|
|
member a: int optional=True
|
|
member b: UserDefOne optional=True
|
|
member c: str optional=False
|
|
object :obj-EVENT_D-arg
|
|
member a: EventStructOne optional=False
|
|
member b: str optional=False
|
|
member c: str optional=True
|
|
member enum3: EnumOne optional=True
|
|
object :obj-__org.qemu_x-command-arg
|
|
member a: __org.qemu_x-EnumList optional=False
|
|
member b: __org.qemu_x-StructList optional=False
|
|
member c: __org.qemu_x-Union2 optional=False
|
|
member d: __org.qemu_x-Alt optional=False
|
|
object :obj-anyList-wrapper
|
|
member data: anyList optional=False
|
|
object :obj-boolList-wrapper
|
|
member data: boolList optional=False
|
|
object :obj-guest-get-time-arg
|
|
member a: int optional=False
|
|
member b: int optional=True
|
|
object :obj-guest-sync-arg
|
|
member arg: any optional=False
|
|
object :obj-int16List-wrapper
|
|
member data: int16List optional=False
|
|
object :obj-int32List-wrapper
|
|
member data: int32List optional=False
|
|
object :obj-int64List-wrapper
|
|
member data: int64List optional=False
|
|
object :obj-int8List-wrapper
|
|
member data: int8List optional=False
|
|
object :obj-intList-wrapper
|
|
member data: intList optional=False
|
|
object :obj-numberList-wrapper
|
|
member data: numberList optional=False
|
|
object :obj-sizeList-wrapper
|
|
member data: sizeList optional=False
|
|
object :obj-str-wrapper
|
|
member data: str optional=False
|
|
object :obj-strList-wrapper
|
|
member data: strList optional=False
|
|
object :obj-uint16List-wrapper
|
|
member data: uint16List optional=False
|
|
object :obj-uint32List-wrapper
|
|
member data: uint32List optional=False
|
|
object :obj-uint64List-wrapper
|
|
member data: uint64List optional=False
|
|
object :obj-uint8List-wrapper
|
|
member data: uint8List optional=False
|
|
object :obj-user_def_cmd1-arg
|
|
member ud1a: UserDefOne optional=False
|
|
object :obj-user_def_cmd2-arg
|
|
member ud1a: UserDefOne optional=False
|
|
member ud1b: UserDefOne optional=True
|
|
alternate AltIntNum
|
|
case i: int
|
|
case n: number
|
|
enum AltIntNumKind ['i', 'n']
|
|
alternate AltNumInt
|
|
case n: number
|
|
case i: int
|
|
enum AltNumIntKind ['n', 'i']
|
|
alternate AltNumStr
|
|
case n: number
|
|
case s: str
|
|
enum AltNumStrKind ['n', 's']
|
|
alternate AltStrBool
|
|
case s: str
|
|
case b: bool
|
|
enum AltStrBoolKind ['s', 'b']
|
|
alternate AltStrInt
|
|
case s: str
|
|
case i: int
|
|
enum AltStrIntKind ['s', 'i']
|
|
alternate AltStrNum
|
|
case s: str
|
|
case n: number
|
|
enum AltStrNumKind ['s', 'n']
|
|
event EVENT_A None
|
|
event EVENT_B None
|
|
event EVENT_C :obj-EVENT_C-arg
|
|
event EVENT_D :obj-EVENT_D-arg
|
|
enum EnumOne ['value1', 'value2', 'value3']
|
|
object EventStructOne
|
|
member struct1: UserDefOne optional=False
|
|
member string: str optional=False
|
|
member enum2: EnumOne optional=True
|
|
object ForceArrays
|
|
member unused1: UserDefOneList optional=False
|
|
member unused2: UserDefTwoList optional=False
|
|
enum MyEnum []
|
|
object NestedEnumsOne
|
|
member enum1: EnumOne optional=False
|
|
member enum2: EnumOne optional=True
|
|
member enum3: EnumOne optional=False
|
|
member enum4: EnumOne optional=True
|
|
enum QEnumTwo ['value1', 'value2']
|
|
prefix QENUM_TWO
|
|
object UserDefA
|
|
member boolean: bool optional=False
|
|
member a_b: int optional=True
|
|
alternate UserDefAlternate
|
|
case uda: UserDefA
|
|
case s: str
|
|
case i: int
|
|
enum UserDefAlternateKind ['uda', 's', 'i']
|
|
object UserDefB
|
|
member intb: int optional=False
|
|
member a-b: bool optional=True
|
|
object UserDefC
|
|
member string1: str optional=False
|
|
member string2: str optional=False
|
|
object UserDefFlatUnion
|
|
base UserDefUnionBase
|
|
tag enum1
|
|
case value1: UserDefA
|
|
case value2: UserDefB
|
|
case value3: UserDefB
|
|
object UserDefFlatUnion2
|
|
base UserDefUnionBase
|
|
tag enum1
|
|
case value1: UserDefC
|
|
case value2: UserDefB
|
|
case value3: UserDefA
|
|
object UserDefNativeListUnion
|
|
case integer: :obj-intList-wrapper
|
|
case s8: :obj-int8List-wrapper
|
|
case s16: :obj-int16List-wrapper
|
|
case s32: :obj-int32List-wrapper
|
|
case s64: :obj-int64List-wrapper
|
|
case u8: :obj-uint8List-wrapper
|
|
case u16: :obj-uint16List-wrapper
|
|
case u32: :obj-uint32List-wrapper
|
|
case u64: :obj-uint64List-wrapper
|
|
case number: :obj-numberList-wrapper
|
|
case boolean: :obj-boolList-wrapper
|
|
case string: :obj-strList-wrapper
|
|
case sizes: :obj-sizeList-wrapper
|
|
case any: :obj-anyList-wrapper
|
|
enum UserDefNativeListUnionKind ['integer', 's8', 's16', 's32', 's64', 'u8', 'u16', 'u32', 'u64', 'number', 'boolean', 'string', 'sizes', 'any']
|
|
object UserDefOne
|
|
base UserDefZero
|
|
member string: str optional=False
|
|
member enum1: EnumOne optional=True
|
|
object UserDefOptions
|
|
member i64: intList optional=True
|
|
member u64: uint64List optional=True
|
|
member u16: uint16List optional=True
|
|
member i64x: int optional=True
|
|
member u64x: uint64 optional=True
|
|
object UserDefTwo
|
|
member string0: str optional=False
|
|
member dict1: UserDefTwoDict optional=False
|
|
object UserDefTwoDict
|
|
member string1: str optional=False
|
|
member dict2: UserDefTwoDictDict optional=False
|
|
member dict3: UserDefTwoDictDict optional=True
|
|
object UserDefTwoDictDict
|
|
member userdef: UserDefOne optional=False
|
|
member string: str optional=False
|
|
object UserDefUnionBase
|
|
base UserDefZero
|
|
member string: str optional=False
|
|
member enum1: EnumOne optional=False
|
|
object UserDefZero
|
|
member integer: int optional=False
|
|
event __ORG.QEMU_X-EVENT __org.qemu_x-Struct
|
|
alternate __org.qemu_x-Alt
|
|
case __org.qemu_x-branch: str
|
|
case b: __org.qemu_x-Base
|
|
enum __org.qemu_x-AltKind ['__org.qemu_x-branch', 'b']
|
|
object __org.qemu_x-Base
|
|
member __org.qemu_x-member1: __org.qemu_x-Enum optional=False
|
|
enum __org.qemu_x-Enum ['__org.qemu_x-value']
|
|
object __org.qemu_x-Struct
|
|
base __org.qemu_x-Base
|
|
member __org.qemu_x-member2: str optional=False
|
|
object __org.qemu_x-Struct2
|
|
member array: __org.qemu_x-Union1List optional=False
|
|
object __org.qemu_x-Union1
|
|
case __org.qemu_x-branch: :obj-str-wrapper
|
|
enum __org.qemu_x-Union1Kind ['__org.qemu_x-branch']
|
|
object __org.qemu_x-Union2
|
|
base __org.qemu_x-Base
|
|
tag __org.qemu_x-member1
|
|
case __org.qemu_x-value: __org.qemu_x-Struct2
|
|
command __org.qemu_x-command :obj-__org.qemu_x-command-arg -> __org.qemu_x-Union1
|
|
gen=True success_response=True
|
|
command guest-get-time :obj-guest-get-time-arg -> int
|
|
gen=True success_response=True
|
|
command guest-sync :obj-guest-sync-arg -> any
|
|
gen=True success_response=True
|
|
command user_def_cmd None -> None
|
|
gen=True success_response=True
|
|
command user_def_cmd1 :obj-user_def_cmd1-arg -> None
|
|
gen=True success_response=True
|
|
command user_def_cmd2 :obj-user_def_cmd2-arg -> UserDefTwo
|
|
gen=True success_response=True
|