diff mbox series

[v2,41/44] qdev: Move base property types to qom/property-types.c

Message ID 20201104160021.2342108-42-ehabkost@redhat.com
State New
Headers show
Series Make qdev static property API usable by any QOM type | expand

Commit Message

Eduardo Habkost Nov. 4, 2020, 4 p.m. UTC
Move all property types from qdev-properties.c to
qom/property-types.c.

Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
---
Changes v1 -> v2:
* Rebased after changes in previous patches in the series
---
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: "Daniel P. Berrangé" <berrange@redhat.com>
Cc: Eduardo Habkost <ehabkost@redhat.com>
Cc: qemu-devel@nongnu.org
---
 include/hw/qdev-properties.h | 179 +-----------
 include/qom/property-types.h | 185 ++++++++++++
 hw/core/qdev-properties.c    | 537 ----------------------------------
 qom/property-types.c         | 545 +++++++++++++++++++++++++++++++++++
 qom/meson.build              |   1 +
 5 files changed, 732 insertions(+), 715 deletions(-)
 create mode 100644 include/qom/property-types.h
 create mode 100644 qom/property-types.c

Comments

Paolo Bonzini Nov. 4, 2020, 4:36 p.m. UTC | #1
On 04/11/20 17:00, Eduardo Habkost wrote:
> Move all property types from qdev-properties.c to

> qom/property-types.c.

> 

> Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>

> ---

> Changes v1 -> v2:

> * Rebased after changes in previous patches in the series

> ---

> Cc: Paolo Bonzini <pbonzini@redhat.com>

> Cc: "Daniel P. Berrangé" <berrange@redhat.com>

> Cc: Eduardo Habkost <ehabkost@redhat.com>

> Cc: qemu-devel@nongnu.org

> ---

>   include/hw/qdev-properties.h | 179 +-----------

>   include/qom/property-types.h | 185 ++++++++++++

>   hw/core/qdev-properties.c    | 537 ----------------------------------

>   qom/property-types.c         | 545 +++++++++++++++++++++++++++++++++++

>   qom/meson.build              |   1 +

>   5 files changed, 732 insertions(+), 715 deletions(-)

>   create mode 100644 include/qom/property-types.h

>   create mode 100644 qom/property-types.c


I would merge property-types.h and field-property.h in a single file.

Actually I wouldn't even bother having separate headers, however it's 
certainly valuable to have headers like you have in patch 42:

Core QOM API Reference
----------------------

....


Field Property API Reference
----------------------------

....



I'm not sure if it's possible to include rST headers in .h files.

Paolo

> diff --git a/include/hw/qdev-properties.h b/include/hw/qdev-properties.h

> index bee26d0319..939b6dbf4e 100644

> --- a/include/hw/qdev-properties.h

> +++ b/include/hw/qdev-properties.h

> @@ -3,184 +3,7 @@

>   

>   #include "hw/qdev-core.h"

>   #include "qom/field-property.h"

> -

> -/*** qdev-properties.c ***/

> -

> -extern const PropertyInfo prop_info_bit;

> -extern const PropertyInfo prop_info_bit64;

> -extern const PropertyInfo prop_info_bool;

> -extern const PropertyInfo prop_info_enum;

> -extern const PropertyInfo prop_info_uint8;

> -extern const PropertyInfo prop_info_uint16;

> -extern const PropertyInfo prop_info_uint32;

> -extern const PropertyInfo prop_info_int32;

> -extern const PropertyInfo prop_info_uint64;

> -extern const PropertyInfo prop_info_int64;

> -extern const PropertyInfo prop_info_size;

> -extern const PropertyInfo prop_info_string;

> -extern const PropertyInfo prop_info_on_off_auto;

> -extern const PropertyInfo prop_info_size32;

> -extern const PropertyInfo prop_info_arraylen;

> -extern const PropertyInfo prop_info_link;

> -

> -#define DEFINE_PROP(_name, _state, _field, _prop, _type, ...) {  \

> -        .qdev_prop_name      = (_name),                          \

> -        .info      = &(_prop),                                   \

> -        .offset    = offsetof(_state, _field)                    \

> -            + type_check(_type, typeof_field(_state, _field)),   \

> -        __VA_ARGS__                                              \

> -        }

> -

> -#define DEFINE_PROP_SIGNED(_name, _state, _field, _defval, _prop, _type) \

> -    DEFINE_PROP(_name, _state, _field, _prop, _type,                     \

> -                .set_default = true,                                     \

> -                .defval.i    = (_type)_defval)

> -

> -#define DEFINE_PROP_SIGNED_NODEFAULT(_name, _state, _field, _prop, _type) \

> -    DEFINE_PROP(_name, _state, _field, _prop, _type)

> -

> -#define DEFINE_PROP_BIT(_name, _state, _field, _bit, _defval)   \

> -    DEFINE_PROP(_name, _state, _field, prop_info_bit, uint32_t, \

> -                .bitnr       = (_bit),                          \

> -                .set_default = true,                            \

> -                .defval.u    = (bool)_defval)

> -

> -#define DEFINE_PROP_UNSIGNED(_name, _state, _field, _defval, _prop, _type) \

> -    DEFINE_PROP(_name, _state, _field, _prop, _type,                       \

> -                .set_default = true,                                       \

> -                .defval.u  = (_type)_defval)

> -

> -#define DEFINE_PROP_UNSIGNED_NODEFAULT(_name, _state, _field, _prop, _type) \

> -    DEFINE_PROP(_name, _state, _field, _prop, _type)

> -

> -#define DEFINE_PROP_BIT64(_name, _state, _field, _bit, _defval)   \

> -    DEFINE_PROP(_name, _state, _field, prop_info_bit64, uint64_t, \

> -                .bitnr    = (_bit),                               \

> -                .set_default = true,                              \

> -                .defval.u  = (bool)_defval)

> -

> -#define DEFINE_PROP_BOOL(_name, _state, _field, _defval)     \

> -    DEFINE_PROP(_name, _state, _field, prop_info_bool, bool, \

> -                .set_default = true,                         \

> -                .defval.u    = (bool)_defval)

> -

> -#define PROP_ARRAY_LEN_PREFIX "len-"

> -

> -/**

> - * DEFINE_PROP_ARRAY:

> - * @_name: name of the array

> - * @_state: name of the device state structure type

> - * @_field: uint32_t field in @_state to hold the array length

> - * @_arrayfield: field in @_state (of type '@_arraytype *') which

> - *               will point to the array

> - * @_arrayprop: PropertyInfo defining what property the array elements have

> - * @_arraytype: C type of the array elements

> - *

> - * Define device properties for a variable-length array _name.  A

> - * static property "len-arrayname" is defined. When the device creator

> - * sets this property to the desired length of array, further dynamic

> - * properties "arrayname[0]", "arrayname[1]", ...  are defined so the

> - * device creator can set the array element values. Setting the

> - * "len-arrayname" property more than once is an error.

> - *

> - * When the array length is set, the @_field member of the device

> - * struct is set to the array length, and @_arrayfield is set to point

> - * to (zero-initialised) memory allocated for the array.  For a zero

> - * length array, @_field will be set to 0 and @_arrayfield to NULL.

> - * It is the responsibility of the device deinit code to free the

> - * @_arrayfield memory.

> - */

> -#define DEFINE_PROP_ARRAY(_name, _state, _field,               \

> -                          _arrayfield, _arrayprop, _arraytype) \

> -    DEFINE_PROP((PROP_ARRAY_LEN_PREFIX _name),                 \

> -                _state, _field, prop_info_arraylen, uint32_t,  \

> -                .set_default = true,                           \

> -                .defval.u = 0,                                 \

> -                .arrayinfo = &(_arrayprop),                    \

> -                .arrayfieldsize = sizeof(_arraytype),          \

> -                .arrayoffset = offsetof(_state, _arrayfield))

> -

> -#define DEFINE_PROP_LINK(_name, _state, _field, _type, _ptr_type)     \

> -    DEFINE_PROP(_name, _state, _field, prop_info_link, _ptr_type,     \

> -                .link_type  = _type)

> -

> -#define DEFINE_PROP_UINT8(_n, _s, _f, _d)                       \

> -    DEFINE_PROP_UNSIGNED(_n, _s, _f, _d, prop_info_uint8, uint8_t)

> -#define DEFINE_PROP_UINT16(_n, _s, _f, _d)                      \

> -    DEFINE_PROP_UNSIGNED(_n, _s, _f, _d, prop_info_uint16, uint16_t)

> -#define DEFINE_PROP_UINT32(_n, _s, _f, _d)                      \

> -    DEFINE_PROP_UNSIGNED(_n, _s, _f, _d, prop_info_uint32, uint32_t)

> -#define DEFINE_PROP_INT32(_n, _s, _f, _d)                      \

> -    DEFINE_PROP_SIGNED(_n, _s, _f, _d, prop_info_int32, int32_t)

> -#define DEFINE_PROP_UINT64(_n, _s, _f, _d)                      \

> -    DEFINE_PROP_UNSIGNED(_n, _s, _f, _d, prop_info_uint64, uint64_t)

> -#define DEFINE_PROP_INT64(_n, _s, _f, _d)                      \

> -    DEFINE_PROP_SIGNED(_n, _s, _f, _d, prop_info_int64, int64_t)

> -#define DEFINE_PROP_SIZE(_n, _s, _f, _d)                       \

> -    DEFINE_PROP_UNSIGNED(_n, _s, _f, _d, prop_info_size, uint64_t)

> -#define DEFINE_PROP_STRING(_n, _s, _f)             \

> -    DEFINE_PROP(_n, _s, _f, prop_info_string, char*)

> -#define DEFINE_PROP_ON_OFF_AUTO(_n, _s, _f, _d) \

> -    DEFINE_PROP_SIGNED(_n, _s, _f, _d, prop_info_on_off_auto, OnOffAuto)

> -#define DEFINE_PROP_SIZE32(_n, _s, _f, _d)                       \

> -    DEFINE_PROP_UNSIGNED(_n, _s, _f, _d, prop_info_size32, uint32_t)

> -

> -#define DEFINE_PROP_END_OF_LIST()               \

> -    {}

> -

> -/*

> - * The PROP_* macros can be used as arguments for

> - * object_class_property_add_field().  They will evaluate to a

> - * pointer to a static variable.

> - */

> -

> -#define FIELD_PROP(def) \

> -    ({ static Property _p = def; &p; })

> -

> -#define PROP_SIGNED(...) \

> -    FIELD_PROP(DEFINE_PROP_SIGNED(NULL, __VA_ARGS__))

> -#define PROP_SIGNED_NODEFAULT(...) \

> -    FIELD_PROP(DEFINE_PROP_SIGNED_NODEFAULT(NULL, __VA_ARGS__))

> -#define PROP_BIT(...) \

> -    FIELD_PROP(DEFINE_PROP_BIT(NULL, __VA_ARGS__))

> -#define PROP_UNSIGNED(...) \

> -    FIELD_PROP(DEFINE_PROP_UNSIGNED(NULL, __VA_ARGS__))

> -#define PROP_UNSIGNED_NODEFAULT(...) \

> -    FIELD_PROP(DEFINE_PROP_UNSIGNED_NODEFAULT(NULL, __VA_ARGS__))

> -#define PROP_BIT64(...) \

> -    FIELD_PROP(DEFINE_PROP_BIT64(NULL, __VA_ARGS__))

> -#define PROP_BOOL(...) \

> -    FIELD_PROP(DEFINE_PROP_BOOL(NULL, __VA_ARGS__))

> -#define PROP_ARRAY(...) \

> -    FIELD_PROP(DEFINE_PROP_ARRAY(NULL, __VA_ARGS__))

> -#define PROP_LINK(...) \

> -    FIELD_PROP(DEFINE_PROP_LINK(NULL, __VA_ARGS__))

> -#define PROP_UINT8(...) \

> -    FIELD_PROP(DEFINE_PROP_UINT8(NULL, __VA_ARGS__))

> -#define PROP_UINT16(...) \

> -    FIELD_PROP(DEFINE_PROP_UINT16(NULL, __VA_ARGS__))

> -#define PROP_UINT32(...) \

> -    FIELD_PROP(DEFINE_PROP_UINT32(NULL, __VA_ARGS__))

> -#define PROP_INT32(...) \

> -    FIELD_PROP(DEFINE_PROP_INT32(NULL, __VA_ARGS__))

> -#define PROP_UINT64(...) \

> -    FIELD_PROP(DEFINE_PROP_UINT64(NULL, __VA_ARGS__))

> -#define PROP_INT64(...) \

> -    FIELD_PROP(DEFINE_PROP_INT64(NULL, __VA_ARGS__))

> -#define PROP_SIZE(...) \

> -    FIELD_PROP(DEFINE_PROP_SIZE(NULL, __VA_ARGS__))

> -#define PROP_STRING(...) \

> -    FIELD_PROP(DEFINE_PROP_STRING(NULL, __VA_ARGS__))

> -#define PROP_ON_OFF_AUTO(...) \

> -    FIELD_PROP(DEFINE_PROP_ON_OFF_AUTO(NULL, __VA_ARGS__))

> -#define PROP_SIZE32(...) \

> -    FIELD_PROP(DEFINE_PROP_SIZE32(NULL, __VA_ARGS__))

> -#define PROP_UUID(...) \

> -    FIELD_PROP(DEFINE_PROP_UUID(NULL, __VA_ARGS__))

> -#define PROP_UUID_NODEFAULT(...) \

> -    FIELD_PROP(DEFINE_PROP_UUID_NODEFAULT(NULL, __VA_ARGS__))

> -#define PROP_END_OF_LIST(...) \

> -    FIELD_PROP(DEFINE_PROP_END_OF_LIST(NULL, __VA_ARGS__))

> +#include "qom/property-types.h"

>   

>   /*

>    * Set properties between creation and realization.

> diff --git a/include/qom/property-types.h b/include/qom/property-types.h

> new file mode 100644

> index 0000000000..75f758e835

> --- /dev/null

> +++ b/include/qom/property-types.h

> @@ -0,0 +1,185 @@

> +/*

> + * QOM field property types

> + */

> +#ifndef QOM_PROPERTY_TYPES_H

> +#define QOM_PROPERTY_TYPES_H

> +

> +#include "qom/field-property.h"

> +

> +extern const PropertyInfo prop_info_bit;

> +extern const PropertyInfo prop_info_bit64;

> +extern const PropertyInfo prop_info_bool;

> +extern const PropertyInfo prop_info_enum;

> +extern const PropertyInfo prop_info_uint8;

> +extern const PropertyInfo prop_info_uint16;

> +extern const PropertyInfo prop_info_uint32;

> +extern const PropertyInfo prop_info_int32;

> +extern const PropertyInfo prop_info_uint64;

> +extern const PropertyInfo prop_info_int64;

> +extern const PropertyInfo prop_info_size;

> +extern const PropertyInfo prop_info_string;

> +extern const PropertyInfo prop_info_on_off_auto;

> +extern const PropertyInfo prop_info_size32;

> +extern const PropertyInfo prop_info_arraylen;

> +extern const PropertyInfo prop_info_link;

> +

> +#define DEFINE_PROP(_name, _state, _field, _prop, _type, ...) {  \

> +        .qdev_prop_name      = (_name),                          \

> +        .info      = &(_prop),                                   \

> +        .offset    = offsetof(_state, _field)                    \

> +            + type_check(_type, typeof_field(_state, _field)),   \

> +        __VA_ARGS__                                              \

> +        }

> +

> +#define DEFINE_PROP_SIGNED(_name, _state, _field, _defval, _prop, _type) \

> +    DEFINE_PROP(_name, _state, _field, _prop, _type,                     \

> +                .set_default = true,                                     \

> +                .defval.i    = (_type)_defval)

> +

> +#define DEFINE_PROP_SIGNED_NODEFAULT(_name, _state, _field, _prop, _type) \

> +    DEFINE_PROP(_name, _state, _field, _prop, _type)

> +

> +#define DEFINE_PROP_BIT(_name, _state, _field, _bit, _defval)   \

> +    DEFINE_PROP(_name, _state, _field, prop_info_bit, uint32_t, \

> +                .bitnr       = (_bit),                          \

> +                .set_default = true,                            \

> +                .defval.u    = (bool)_defval)

> +

> +#define DEFINE_PROP_UNSIGNED(_name, _state, _field, _defval, _prop, _type) \

> +    DEFINE_PROP(_name, _state, _field, _prop, _type,                       \

> +                .set_default = true,                                       \

> +                .defval.u  = (_type)_defval)

> +

> +#define DEFINE_PROP_UNSIGNED_NODEFAULT(_name, _state, _field, _prop, _type) \

> +    DEFINE_PROP(_name, _state, _field, _prop, _type)

> +

> +#define DEFINE_PROP_BIT64(_name, _state, _field, _bit, _defval)   \

> +    DEFINE_PROP(_name, _state, _field, prop_info_bit64, uint64_t, \

> +                .bitnr    = (_bit),                               \

> +                .set_default = true,                              \

> +                .defval.u  = (bool)_defval)

> +

> +#define DEFINE_PROP_BOOL(_name, _state, _field, _defval)     \

> +    DEFINE_PROP(_name, _state, _field, prop_info_bool, bool, \

> +                .set_default = true,                         \

> +                .defval.u    = (bool)_defval)

> +

> +#define PROP_ARRAY_LEN_PREFIX "len-"

> +

> +/**

> + * DEFINE_PROP_ARRAY:

> + * @_name: name of the array

> + * @_state: name of the device state structure type

> + * @_field: uint32_t field in @_state to hold the array length

> + * @_arrayfield: field in @_state (of type '@_arraytype *') which

> + *               will point to the array

> + * @_arrayprop: PropertyInfo defining what property the array elements have

> + * @_arraytype: C type of the array elements

> + *

> + * Define device properties for a variable-length array _name.  A

> + * static property "len-arrayname" is defined. When the device creator

> + * sets this property to the desired length of array, further dynamic

> + * properties "arrayname[0]", "arrayname[1]", ...  are defined so the

> + * device creator can set the array element values. Setting the

> + * "len-arrayname" property more than once is an error.

> + *

> + * When the array length is set, the @_field member of the device

> + * struct is set to the array length, and @_arrayfield is set to point

> + * to (zero-initialised) memory allocated for the array.  For a zero

> + * length array, @_field will be set to 0 and @_arrayfield to NULL.

> + * It is the responsibility of the device deinit code to free the

> + * @_arrayfield memory.

> + */

> +#define DEFINE_PROP_ARRAY(_name, _state, _field,               \

> +                          _arrayfield, _arrayprop, _arraytype) \

> +    DEFINE_PROP((PROP_ARRAY_LEN_PREFIX _name),                 \

> +                _state, _field, prop_info_arraylen, uint32_t,  \

> +                .set_default = true,                           \

> +                .defval.u = 0,                                 \

> +                .arrayinfo = &(_arrayprop),                    \

> +                .arrayfieldsize = sizeof(_arraytype),          \

> +                .arrayoffset = offsetof(_state, _arrayfield))

> +

> +#define DEFINE_PROP_LINK(_name, _state, _field, _type, _ptr_type)     \

> +    DEFINE_PROP(_name, _state, _field, prop_info_link, _ptr_type,     \

> +                .link_type  = _type)

> +

> +#define DEFINE_PROP_UINT8(_n, _s, _f, _d)                       \

> +    DEFINE_PROP_UNSIGNED(_n, _s, _f, _d, prop_info_uint8, uint8_t)

> +#define DEFINE_PROP_UINT16(_n, _s, _f, _d)                      \

> +    DEFINE_PROP_UNSIGNED(_n, _s, _f, _d, prop_info_uint16, uint16_t)

> +#define DEFINE_PROP_UINT32(_n, _s, _f, _d)                      \

> +    DEFINE_PROP_UNSIGNED(_n, _s, _f, _d, prop_info_uint32, uint32_t)

> +#define DEFINE_PROP_INT32(_n, _s, _f, _d)                      \

> +    DEFINE_PROP_SIGNED(_n, _s, _f, _d, prop_info_int32, int32_t)

> +#define DEFINE_PROP_UINT64(_n, _s, _f, _d)                      \

> +    DEFINE_PROP_UNSIGNED(_n, _s, _f, _d, prop_info_uint64, uint64_t)

> +#define DEFINE_PROP_INT64(_n, _s, _f, _d)                      \

> +    DEFINE_PROP_SIGNED(_n, _s, _f, _d, prop_info_int64, int64_t)

> +#define DEFINE_PROP_SIZE(_n, _s, _f, _d)                       \

> +    DEFINE_PROP_UNSIGNED(_n, _s, _f, _d, prop_info_size, uint64_t)

> +#define DEFINE_PROP_STRING(_n, _s, _f)             \

> +    DEFINE_PROP(_n, _s, _f, prop_info_string, char*)

> +#define DEFINE_PROP_ON_OFF_AUTO(_n, _s, _f, _d) \

> +    DEFINE_PROP_SIGNED(_n, _s, _f, _d, prop_info_on_off_auto, OnOffAuto)

> +#define DEFINE_PROP_SIZE32(_n, _s, _f, _d)                       \

> +    DEFINE_PROP_UNSIGNED(_n, _s, _f, _d, prop_info_size32, uint32_t)

> +

> +#define DEFINE_PROP_END_OF_LIST()               \

> +    {}

> +

> +/*

> + * The PROP_* macros can be used as arguments for

> + * object_class_property_add_field().  They will evaluate to a

> + * pointer to a static variable.

> + */

> +

> +#define FIELD_PROP(def) \

> +    ({ static Property _p = def; &p; })

> +

> +#define PROP_SIGNED(...) \

> +    FIELD_PROP(DEFINE_PROP_SIGNED(NULL, __VA_ARGS__))

> +#define PROP_SIGNED_NODEFAULT(...) \

> +    FIELD_PROP(DEFINE_PROP_SIGNED_NODEFAULT(NULL, __VA_ARGS__))

> +#define PROP_BIT(...) \

> +    FIELD_PROP(DEFINE_PROP_BIT(NULL, __VA_ARGS__))

> +#define PROP_UNSIGNED(...) \

> +    FIELD_PROP(DEFINE_PROP_UNSIGNED(NULL, __VA_ARGS__))

> +#define PROP_UNSIGNED_NODEFAULT(...) \

> +    FIELD_PROP(DEFINE_PROP_UNSIGNED_NODEFAULT(NULL, __VA_ARGS__))

> +#define PROP_BIT64(...) \

> +    FIELD_PROP(DEFINE_PROP_BIT64(NULL, __VA_ARGS__))

> +#define PROP_BOOL(...) \

> +    FIELD_PROP(DEFINE_PROP_BOOL(NULL, __VA_ARGS__))

> +#define PROP_ARRAY(...) \

> +    FIELD_PROP(DEFINE_PROP_ARRAY(NULL, __VA_ARGS__))

> +#define PROP_LINK(...) \

> +    FIELD_PROP(DEFINE_PROP_LINK(NULL, __VA_ARGS__))

> +#define PROP_UINT8(...) \

> +    FIELD_PROP(DEFINE_PROP_UINT8(NULL, __VA_ARGS__))

> +#define PROP_UINT16(...) \

> +    FIELD_PROP(DEFINE_PROP_UINT16(NULL, __VA_ARGS__))

> +#define PROP_UINT32(...) \

> +    FIELD_PROP(DEFINE_PROP_UINT32(NULL, __VA_ARGS__))

> +#define PROP_INT32(...) \

> +    FIELD_PROP(DEFINE_PROP_INT32(NULL, __VA_ARGS__))

> +#define PROP_UINT64(...) \

> +    FIELD_PROP(DEFINE_PROP_UINT64(NULL, __VA_ARGS__))

> +#define PROP_INT64(...) \

> +    FIELD_PROP(DEFINE_PROP_INT64(NULL, __VA_ARGS__))

> +#define PROP_SIZE(...) \

> +    FIELD_PROP(DEFINE_PROP_SIZE(NULL, __VA_ARGS__))

> +#define PROP_STRING(...) \

> +    FIELD_PROP(DEFINE_PROP_STRING(NULL, __VA_ARGS__))

> +#define PROP_ON_OFF_AUTO(...) \

> +    FIELD_PROP(DEFINE_PROP_ON_OFF_AUTO(NULL, __VA_ARGS__))

> +#define PROP_SIZE32(...) \

> +    FIELD_PROP(DEFINE_PROP_SIZE32(NULL, __VA_ARGS__))

> +#define PROP_UUID(...) \

> +    FIELD_PROP(DEFINE_PROP_UUID(NULL, __VA_ARGS__))

> +#define PROP_UUID_NODEFAULT(...) \

> +    FIELD_PROP(DEFINE_PROP_UUID_NODEFAULT(NULL, __VA_ARGS__))

> +#define PROP_END_OF_LIST(...) \

> +    FIELD_PROP(DEFINE_PROP_END_OF_LIST(NULL, __VA_ARGS__))

> +

> +#endif

> diff --git a/hw/core/qdev-properties.c b/hw/core/qdev-properties.c

> index b75730f15c..5bb4ff5f46 100644

> --- a/hw/core/qdev-properties.c

> +++ b/hw/core/qdev-properties.c

> @@ -50,496 +50,6 @@ void qdev_prop_allow_set_link_before_realize(const Object *obj,

>       }

>   }

>   

> -void field_prop_get_enum(Object *obj, Visitor *v, const char *name,

> -                         void *opaque, Error **errp)

> -{

> -    Property *prop = opaque;

> -    int *ptr = object_field_prop_ptr(obj, prop);

> -

> -    visit_type_enum(v, name, ptr, prop->info->enum_table, errp);

> -}

> -

> -void field_prop_set_enum(Object *obj, Visitor *v, const char *name,

> -                         void *opaque, Error **errp)

> -{

> -    Property *prop = opaque;

> -    int *ptr = object_field_prop_ptr(obj, prop);

> -

> -    visit_type_enum(v, name, ptr, prop->info->enum_table, errp);

> -}

> -

> -void field_prop_set_default_value_enum(ObjectProperty *op,

> -                                       const Property *prop)

> -{

> -    object_property_set_default_str(op,

> -        qapi_enum_lookup(prop->info->enum_table, prop->defval.i));

> -}

> -

> -const PropertyInfo prop_info_enum = {

> -    .name  = "enum",

> -    .get   = field_prop_get_enum,

> -    .set   = field_prop_set_enum,

> -    .set_default_value = field_prop_set_default_value_enum,

> -};

> -

> -/* Bit */

> -

> -static uint32_t qdev_get_prop_mask(Property *prop)

> -{

> -    assert(prop->info == &prop_info_bit);

> -    return 0x1 << prop->bitnr;

> -}

> -

> -static void bit_prop_set(Object *obj, Property *props, bool val)

> -{

> -    uint32_t *p = object_field_prop_ptr(obj, props);

> -    uint32_t mask = qdev_get_prop_mask(props);

> -    if (val) {

> -        *p |= mask;

> -    } else {

> -        *p &= ~mask;

> -    }

> -}

> -

> -static void prop_get_bit(Object *obj, Visitor *v, const char *name,

> -                         void *opaque, Error **errp)

> -{

> -    Property *prop = opaque;

> -    uint32_t *p = object_field_prop_ptr(obj, prop);

> -    bool value = (*p & qdev_get_prop_mask(prop)) != 0;

> -

> -    visit_type_bool(v, name, &value, errp);

> -}

> -

> -static void prop_set_bit(Object *obj, Visitor *v, const char *name,

> -                         void *opaque, Error **errp)

> -{

> -    Property *prop = opaque;

> -    bool value;

> -

> -    if (!visit_type_bool(v, name, &value, errp)) {

> -        return;

> -    }

> -    bit_prop_set(obj, prop, value);

> -}

> -

> -static void set_default_value_bool(ObjectProperty *op, const Property *prop)

> -{

> -    object_property_set_default_bool(op, prop->defval.u);

> -}

> -

> -const PropertyInfo prop_info_bit = {

> -    .name  = "bool",

> -    .description = "on/off",

> -    .get   = prop_get_bit,

> -    .set   = prop_set_bit,

> -    .set_default_value = set_default_value_bool,

> -};

> -

> -/* Bit64 */

> -

> -static uint64_t qdev_get_prop_mask64(Property *prop)

> -{

> -    assert(prop->info == &prop_info_bit64);

> -    return 0x1ull << prop->bitnr;

> -}

> -

> -static void bit64_prop_set(Object *obj, Property *props, bool val)

> -{

> -    uint64_t *p = object_field_prop_ptr(obj, props);

> -    uint64_t mask = qdev_get_prop_mask64(props);

> -    if (val) {

> -        *p |= mask;

> -    } else {

> -        *p &= ~mask;

> -    }

> -}

> -

> -static void prop_get_bit64(Object *obj, Visitor *v, const char *name,

> -                           void *opaque, Error **errp)

> -{

> -    Property *prop = opaque;

> -    uint64_t *p = object_field_prop_ptr(obj, prop);

> -    bool value = (*p & qdev_get_prop_mask64(prop)) != 0;

> -

> -    visit_type_bool(v, name, &value, errp);

> -}

> -

> -static void prop_set_bit64(Object *obj, Visitor *v, const char *name,

> -                           void *opaque, Error **errp)

> -{

> -    Property *prop = opaque;

> -    bool value;

> -

> -    if (!visit_type_bool(v, name, &value, errp)) {

> -        return;

> -    }

> -    bit64_prop_set(obj, prop, value);

> -}

> -

> -const PropertyInfo prop_info_bit64 = {

> -    .name  = "bool",

> -    .description = "on/off",

> -    .get   = prop_get_bit64,

> -    .set   = prop_set_bit64,

> -    .set_default_value = set_default_value_bool,

> -};

> -

> -/* --- bool --- */

> -

> -static void get_bool(Object *obj, Visitor *v, const char *name, void *opaque,

> -                     Error **errp)

> -{

> -    Property *prop = opaque;

> -    bool *ptr = object_field_prop_ptr(obj, prop);

> -

> -    visit_type_bool(v, name, ptr, errp);

> -}

> -

> -static void set_bool(Object *obj, Visitor *v, const char *name, void *opaque,

> -                     Error **errp)

> -{

> -    Property *prop = opaque;

> -    bool *ptr = object_field_prop_ptr(obj, prop);

> -

> -    visit_type_bool(v, name, ptr, errp);

> -}

> -

> -const PropertyInfo prop_info_bool = {

> -    .name  = "bool",

> -    .get   = get_bool,

> -    .set   = set_bool,

> -    .set_default_value = set_default_value_bool,

> -};

> -

> -/* --- 8bit integer --- */

> -

> -static void get_uint8(Object *obj, Visitor *v, const char *name, void *opaque,

> -                      Error **errp)

> -{

> -    Property *prop = opaque;

> -    uint8_t *ptr = object_field_prop_ptr(obj, prop);

> -

> -    visit_type_uint8(v, name, ptr, errp);

> -}

> -

> -static void set_uint8(Object *obj, Visitor *v, const char *name, void *opaque,

> -                      Error **errp)

> -{

> -    Property *prop = opaque;

> -    uint8_t *ptr = object_field_prop_ptr(obj, prop);

> -

> -    visit_type_uint8(v, name, ptr, errp);

> -}

> -

> -void field_prop_set_default_value_int(ObjectProperty *op,

> -                                      const Property *prop)

> -{

> -    object_property_set_default_int(op, prop->defval.i);

> -}

> -

> -void field_prop_set_default_value_uint(ObjectProperty *op,

> -                                       const Property *prop)

> -{

> -    object_property_set_default_uint(op, prop->defval.u);

> -}

> -

> -const PropertyInfo prop_info_uint8 = {

> -    .name  = "uint8",

> -    .get   = get_uint8,

> -    .set   = set_uint8,

> -    .set_default_value = field_prop_set_default_value_uint,

> -};

> -

> -/* --- 16bit integer --- */

> -

> -static void get_uint16(Object *obj, Visitor *v, const char *name,

> -                       void *opaque, Error **errp)

> -{

> -    Property *prop = opaque;

> -    uint16_t *ptr = object_field_prop_ptr(obj, prop);

> -

> -    visit_type_uint16(v, name, ptr, errp);

> -}

> -

> -static void set_uint16(Object *obj, Visitor *v, const char *name,

> -                       void *opaque, Error **errp)

> -{

> -    Property *prop = opaque;

> -    uint16_t *ptr = object_field_prop_ptr(obj, prop);

> -

> -    visit_type_uint16(v, name, ptr, errp);

> -}

> -

> -const PropertyInfo prop_info_uint16 = {

> -    .name  = "uint16",

> -    .get   = get_uint16,

> -    .set   = set_uint16,

> -    .set_default_value = field_prop_set_default_value_uint,

> -};

> -

> -/* --- 32bit integer --- */

> -

> -static void get_uint32(Object *obj, Visitor *v, const char *name,

> -                       void *opaque, Error **errp)

> -{

> -    Property *prop = opaque;

> -    uint32_t *ptr = object_field_prop_ptr(obj, prop);

> -

> -    visit_type_uint32(v, name, ptr, errp);

> -}

> -

> -static void set_uint32(Object *obj, Visitor *v, const char *name,

> -                       void *opaque, Error **errp)

> -{

> -    Property *prop = opaque;

> -    uint32_t *ptr = object_field_prop_ptr(obj, prop);

> -

> -    visit_type_uint32(v, name, ptr, errp);

> -}

> -

> -void field_prop_get_int32(Object *obj, Visitor *v, const char *name,

> -                          void *opaque, Error **errp)

> -{

> -    Property *prop = opaque;

> -    int32_t *ptr = object_field_prop_ptr(obj, prop);

> -

> -    visit_type_int32(v, name, ptr, errp);

> -}

> -

> -static void set_int32(Object *obj, Visitor *v, const char *name, void *opaque,

> -                      Error **errp)

> -{

> -    Property *prop = opaque;

> -    int32_t *ptr = object_field_prop_ptr(obj, prop);

> -

> -    visit_type_int32(v, name, ptr, errp);

> -}

> -

> -const PropertyInfo prop_info_uint32 = {

> -    .name  = "uint32",

> -    .get   = get_uint32,

> -    .set   = set_uint32,

> -    .set_default_value = field_prop_set_default_value_uint,

> -};

> -

> -const PropertyInfo prop_info_int32 = {

> -    .name  = "int32",

> -    .get   = field_prop_get_int32,

> -    .set   = set_int32,

> -    .set_default_value = field_prop_set_default_value_int,

> -};

> -

> -/* --- 64bit integer --- */

> -

> -static void get_uint64(Object *obj, Visitor *v, const char *name,

> -                       void *opaque, Error **errp)

> -{

> -    Property *prop = opaque;

> -    uint64_t *ptr = object_field_prop_ptr(obj, prop);

> -

> -    visit_type_uint64(v, name, ptr, errp);

> -}

> -

> -static void set_uint64(Object *obj, Visitor *v, const char *name,

> -                       void *opaque, Error **errp)

> -{

> -    Property *prop = opaque;

> -    uint64_t *ptr = object_field_prop_ptr(obj, prop);

> -

> -    visit_type_uint64(v, name, ptr, errp);

> -}

> -

> -static void get_int64(Object *obj, Visitor *v, const char *name,

> -                      void *opaque, Error **errp)

> -{

> -    Property *prop = opaque;

> -    int64_t *ptr = object_field_prop_ptr(obj, prop);

> -

> -    visit_type_int64(v, name, ptr, errp);

> -}

> -

> -static void set_int64(Object *obj, Visitor *v, const char *name,

> -                      void *opaque, Error **errp)

> -{

> -    Property *prop = opaque;

> -    int64_t *ptr = object_field_prop_ptr(obj, prop);

> -

> -    visit_type_int64(v, name, ptr, errp);

> -}

> -

> -const PropertyInfo prop_info_uint64 = {

> -    .name  = "uint64",

> -    .get   = get_uint64,

> -    .set   = set_uint64,

> -    .set_default_value = field_prop_set_default_value_uint,

> -};

> -

> -const PropertyInfo prop_info_int64 = {

> -    .name  = "int64",

> -    .get   = get_int64,

> -    .set   = set_int64,

> -    .set_default_value = field_prop_set_default_value_int,

> -};

> -

> -/* --- string --- */

> -

> -static void release_string(Object *obj, const char *name, void *opaque)

> -{

> -    Property *prop = opaque;

> -    g_free(*(char **)object_field_prop_ptr(obj, prop));

> -}

> -

> -static void get_string(Object *obj, Visitor *v, const char *name,

> -                       void *opaque, Error **errp)

> -{

> -    Property *prop = opaque;

> -    char **ptr = object_field_prop_ptr(obj, prop);

> -

> -    if (!*ptr) {

> -        char *str = (char *)"";

> -        visit_type_str(v, name, &str, errp);

> -    } else {

> -        visit_type_str(v, name, ptr, errp);

> -    }

> -}

> -

> -static void set_string(Object *obj, Visitor *v, const char *name,

> -                       void *opaque, Error **errp)

> -{

> -    Property *prop = opaque;

> -    char **ptr = object_field_prop_ptr(obj, prop);

> -    char *str;

> -

> -    if (!visit_type_str(v, name, &str, errp)) {

> -        return;

> -    }

> -    g_free(*ptr);

> -    *ptr = str;

> -}

> -

> -const PropertyInfo prop_info_string = {

> -    .name  = "str",

> -    .release = release_string,

> -    .get   = get_string,

> -    .set   = set_string,

> -};

> -

> -/* --- on/off/auto --- */

> -

> -const PropertyInfo prop_info_on_off_auto = {

> -    .name = "OnOffAuto",

> -    .description = "on/off/auto",

> -    .enum_table = &OnOffAuto_lookup,

> -    .get = field_prop_get_enum,

> -    .set = field_prop_set_enum,

> -    .set_default_value = field_prop_set_default_value_enum,

> -};

> -

> -/* --- 32bit unsigned int 'size' type --- */

> -

> -void field_prop_get_size32(Object *obj, Visitor *v, const char *name,

> -                           void *opaque, Error **errp)

> -{

> -    Property *prop = opaque;

> -    uint32_t *ptr = object_field_prop_ptr(obj, prop);

> -    uint64_t value = *ptr;

> -

> -    visit_type_size(v, name, &value, errp);

> -}

> -

> -static void set_size32(Object *obj, Visitor *v, const char *name, void *opaque,

> -                       Error **errp)

> -{

> -    Property *prop = opaque;

> -    uint32_t *ptr = object_field_prop_ptr(obj, prop);

> -    uint64_t value;

> -

> -    if (!visit_type_size(v, name, &value, errp)) {

> -        return;

> -    }

> -

> -    if (value > UINT32_MAX) {

> -        error_setg(errp,

> -                   "Property %s.%s doesn't take value %" PRIu64

> -                   " (maximum: %u)",

> -                   object_get_typename(obj), name, value, UINT32_MAX);

> -        return;

> -    }

> -

> -    *ptr = value;

> -}

> -

> -const PropertyInfo prop_info_size32 = {

> -    .name  = "size",

> -    .get = field_prop_get_size32,

> -    .set = set_size32,

> -    .set_default_value = field_prop_set_default_value_uint,

> -};

> -

> -/* --- support for array properties --- */

> -

> -static void set_prop_arraylen(Object *obj, Visitor *v, const char *name,

> -                              void *opaque, Error **errp)

> -{

> -    /* Setter for the property which defines the length of a

> -     * variable-sized property array. As well as actually setting the

> -     * array-length field in the device struct, we have to create the

> -     * array itself and dynamically add the corresponding properties.

> -     */

> -    Property *prop = opaque;

> -    ObjectProperty *op = object_property_find_err(obj, name, &error_abort);

> -    uint32_t *alenptr = object_field_prop_ptr(obj, prop);

> -    void **arrayptr = (void *)obj + prop->arrayoffset;

> -    void *eltptr;

> -    const char *arrayname;

> -    int i;

> -

> -    if (*alenptr) {

> -        error_setg(errp, "array size property %s may not be set more than once",

> -                   name);

> -        return;

> -    }

> -    if (!visit_type_uint32(v, name, alenptr, errp)) {

> -        return;

> -    }

> -    if (!*alenptr) {

> -        return;

> -    }

> -

> -    /* DEFINE_PROP_ARRAY guarantees that name should start with this prefix;

> -     * strip it off so we can get the name of the array itself.

> -     */

> -    assert(strncmp(name, PROP_ARRAY_LEN_PREFIX,

> -                   strlen(PROP_ARRAY_LEN_PREFIX)) == 0);

> -    arrayname = name + strlen(PROP_ARRAY_LEN_PREFIX);

> -

> -    /* Note that it is the responsibility of the individual device's deinit

> -     * to free the array proper.

> -     */

> -    *arrayptr = eltptr = g_malloc0(*alenptr * prop->arrayfieldsize);

> -    for (i = 0; i < *alenptr; i++, eltptr += prop->arrayfieldsize) {

> -        g_autofree char *propname = g_strdup_printf("%s[%d]", arrayname, i);

> -        Property *arrayprop = g_new0(Property, 1);

> -        arrayprop->info = prop->arrayinfo;

> -        /* This ugly piece of pointer arithmetic sets up the offset so

> -         * that when the underlying get/set hooks call qdev_get_prop_ptr

> -         * they get the right answer despite the array element not actually

> -         * being inside the device struct.

> -         */

> -        arrayprop->offset = eltptr - (void *)obj;

> -        assert(object_field_prop_ptr(obj, arrayprop) == eltptr);

> -        object_property_add_field(obj, propname, arrayprop, op->allow_set);

> -    }

> -}

> -

> -const PropertyInfo prop_info_arraylen = {

> -    .name = "uint32",

> -    .get = get_uint32,

> -    .set = set_prop_arraylen,

> -    .set_default_value = field_prop_set_default_value_uint,

> -};

> -

>   /* --- public helpers --- */

>   

>   static Property *qdev_prop_walk(Property *props, const char *name)

> @@ -712,53 +222,6 @@ void qdev_prop_set_globals(DeviceState *dev)

>                                 dev->hotplugged ? NULL : &error_fatal);

>   }

>   

> -/* --- 64bit unsigned int 'size' type --- */

> -

> -static void get_size(Object *obj, Visitor *v, const char *name, void *opaque,

> -                     Error **errp)

> -{

> -    Property *prop = opaque;

> -    uint64_t *ptr = object_field_prop_ptr(obj, prop);

> -

> -    visit_type_size(v, name, ptr, errp);

> -}

> -

> -static void set_size(Object *obj, Visitor *v, const char *name, void *opaque,

> -                     Error **errp)

> -{

> -    Property *prop = opaque;

> -    uint64_t *ptr = object_field_prop_ptr(obj, prop);

> -

> -    visit_type_size(v, name, ptr, errp);

> -}

> -

> -const PropertyInfo prop_info_size = {

> -    .name  = "size",

> -    .get = get_size,

> -    .set = set_size,

> -    .set_default_value = field_prop_set_default_value_uint,

> -};

> -

> -/* --- object link property --- */

> -

> -static ObjectProperty *create_link_property(ObjectClass *oc, const char *name,

> -                                            Property *prop)

> -{

> -    /*

> -     * NOTE: object_property_allow_set_link is unconditional, but

> -     *       ObjectProperty.allow_set may be set for the property too.

> -     */

> -    return object_class_property_add_link(oc, name, prop->link_type,

> -                                          prop->offset,

> -                                          object_property_allow_set_link,

> -                                          OBJ_PROP_LINK_STRONG);

> -}

> -

> -const PropertyInfo prop_info_link = {

> -    .name = "link",

> -    .create = create_link_property,

> -};

> -

>   void qdev_property_add_static(DeviceState *dev, Property *prop)

>   {

>       object_property_add_field(OBJECT(dev), prop->qdev_prop_name, prop,

> diff --git a/qom/property-types.c b/qom/property-types.c

> new file mode 100644

> index 0000000000..f566c05ec2

> --- /dev/null

> +++ b/qom/property-types.c

> @@ -0,0 +1,545 @@

> +#include "qemu/osdep.h"

> +#include "qom/field-property.h"

> +#include "qom/property-types.h"

> +#include "qom/field-property-internal.h"

> +#include "qapi/qapi-types-common.h"

> +#include "qapi/visitor.h"

> +#include "qapi/error.h"

> +#include "qemu/uuid.h"

> +

> +void field_prop_get_enum(Object *obj, Visitor *v, const char *name,

> +                         void *opaque, Error **errp)

> +{

> +    Property *prop = opaque;

> +    int *ptr = object_field_prop_ptr(obj, prop);

> +

> +    visit_type_enum(v, name, ptr, prop->info->enum_table, errp);

> +}

> +

> +void field_prop_set_enum(Object *obj, Visitor *v, const char *name,

> +                         void *opaque, Error **errp)

> +{

> +    Property *prop = opaque;

> +    int *ptr = object_field_prop_ptr(obj, prop);

> +

> +    visit_type_enum(v, name, ptr, prop->info->enum_table, errp);

> +}

> +

> +void field_prop_set_default_value_enum(ObjectProperty *op,

> +                                       const Property *prop)

> +{

> +    object_property_set_default_str(op,

> +        qapi_enum_lookup(prop->info->enum_table, prop->defval.i));

> +}

> +

> +const PropertyInfo prop_info_enum = {

> +    .name  = "enum",

> +    .get   = field_prop_get_enum,

> +    .set   = field_prop_set_enum,

> +    .set_default_value = field_prop_set_default_value_enum,

> +};

> +

> +/* Bit */

> +

> +static uint32_t qdev_get_prop_mask(Property *prop)

> +{

> +    assert(prop->info == &prop_info_bit);

> +    return 0x1 << prop->bitnr;

> +}

> +

> +static void bit_prop_set(Object *obj, Property *props, bool val)

> +{

> +    uint32_t *p = object_field_prop_ptr(obj, props);

> +    uint32_t mask = qdev_get_prop_mask(props);

> +    if (val) {

> +        *p |= mask;

> +    } else {

> +        *p &= ~mask;

> +    }

> +}

> +

> +static void prop_get_bit(Object *obj, Visitor *v, const char *name,

> +                         void *opaque, Error **errp)

> +{

> +    Property *prop = opaque;

> +    uint32_t *p = object_field_prop_ptr(obj, prop);

> +    bool value = (*p & qdev_get_prop_mask(prop)) != 0;

> +

> +    visit_type_bool(v, name, &value, errp);

> +}

> +

> +static void prop_set_bit(Object *obj, Visitor *v, const char *name,

> +                         void *opaque, Error **errp)

> +{

> +    Property *prop = opaque;

> +    bool value;

> +

> +    if (!visit_type_bool(v, name, &value, errp)) {

> +        return;

> +    }

> +    bit_prop_set(obj, prop, value);

> +}

> +

> +static void set_default_value_bool(ObjectProperty *op, const Property *prop)

> +{

> +    object_property_set_default_bool(op, prop->defval.u);

> +}

> +

> +const PropertyInfo prop_info_bit = {

> +    .name  = "bool",

> +    .description = "on/off",

> +    .get   = prop_get_bit,

> +    .set   = prop_set_bit,

> +    .set_default_value = set_default_value_bool,

> +};

> +

> +/* Bit64 */

> +

> +static uint64_t qdev_get_prop_mask64(Property *prop)

> +{

> +    assert(prop->info == &prop_info_bit64);

> +    return 0x1ull << prop->bitnr;

> +}

> +

> +static void bit64_prop_set(Object *obj, Property *props, bool val)

> +{

> +    uint64_t *p = object_field_prop_ptr(obj, props);

> +    uint64_t mask = qdev_get_prop_mask64(props);

> +    if (val) {

> +        *p |= mask;

> +    } else {

> +        *p &= ~mask;

> +    }

> +}

> +

> +static void prop_get_bit64(Object *obj, Visitor *v, const char *name,

> +                           void *opaque, Error **errp)

> +{

> +    Property *prop = opaque;

> +    uint64_t *p = object_field_prop_ptr(obj, prop);

> +    bool value = (*p & qdev_get_prop_mask64(prop)) != 0;

> +

> +    visit_type_bool(v, name, &value, errp);

> +}

> +

> +static void prop_set_bit64(Object *obj, Visitor *v, const char *name,

> +                           void *opaque, Error **errp)

> +{

> +    Property *prop = opaque;

> +    bool value;

> +

> +    if (!visit_type_bool(v, name, &value, errp)) {

> +        return;

> +    }

> +    bit64_prop_set(obj, prop, value);

> +}

> +

> +const PropertyInfo prop_info_bit64 = {

> +    .name  = "bool",

> +    .description = "on/off",

> +    .get   = prop_get_bit64,

> +    .set   = prop_set_bit64,

> +    .set_default_value = set_default_value_bool,

> +};

> +

> +/* --- bool --- */

> +

> +static void get_bool(Object *obj, Visitor *v, const char *name, void *opaque,

> +                     Error **errp)

> +{

> +    Property *prop = opaque;

> +    bool *ptr = object_field_prop_ptr(obj, prop);

> +

> +    visit_type_bool(v, name, ptr, errp);

> +}

> +

> +static void set_bool(Object *obj, Visitor *v, const char *name, void *opaque,

> +                     Error **errp)

> +{

> +    Property *prop = opaque;

> +    bool *ptr = object_field_prop_ptr(obj, prop);

> +

> +    visit_type_bool(v, name, ptr, errp);

> +}

> +

> +const PropertyInfo prop_info_bool = {

> +    .name  = "bool",

> +    .get   = get_bool,

> +    .set   = set_bool,

> +    .set_default_value = set_default_value_bool,

> +};

> +

> +/* --- 8bit integer --- */

> +

> +static void get_uint8(Object *obj, Visitor *v, const char *name, void *opaque,

> +                      Error **errp)

> +{

> +    Property *prop = opaque;

> +    uint8_t *ptr = object_field_prop_ptr(obj, prop);

> +

> +    visit_type_uint8(v, name, ptr, errp);

> +}

> +

> +static void set_uint8(Object *obj, Visitor *v, const char *name, void *opaque,

> +                      Error **errp)

> +{

> +    Property *prop = opaque;

> +    uint8_t *ptr = object_field_prop_ptr(obj, prop);

> +

> +    visit_type_uint8(v, name, ptr, errp);

> +}

> +

> +void field_prop_set_default_value_int(ObjectProperty *op,

> +                                      const Property *prop)

> +{

> +    object_property_set_default_int(op, prop->defval.i);

> +}

> +

> +void field_prop_set_default_value_uint(ObjectProperty *op,

> +                                       const Property *prop)

> +{

> +    object_property_set_default_uint(op, prop->defval.u);

> +}

> +

> +const PropertyInfo prop_info_uint8 = {

> +    .name  = "uint8",

> +    .get   = get_uint8,

> +    .set   = set_uint8,

> +    .set_default_value = field_prop_set_default_value_uint,

> +};

> +

> +/* --- 16bit integer --- */

> +

> +static void get_uint16(Object *obj, Visitor *v, const char *name,

> +                       void *opaque, Error **errp)

> +{

> +    Property *prop = opaque;

> +    uint16_t *ptr = object_field_prop_ptr(obj, prop);

> +

> +    visit_type_uint16(v, name, ptr, errp);

> +}

> +

> +static void set_uint16(Object *obj, Visitor *v, const char *name,

> +                       void *opaque, Error **errp)

> +{

> +    Property *prop = opaque;

> +    uint16_t *ptr = object_field_prop_ptr(obj, prop);

> +

> +    visit_type_uint16(v, name, ptr, errp);

> +}

> +

> +const PropertyInfo prop_info_uint16 = {

> +    .name  = "uint16",

> +    .get   = get_uint16,

> +    .set   = set_uint16,

> +    .set_default_value = field_prop_set_default_value_uint,

> +};

> +

> +/* --- 32bit integer --- */

> +

> +static void get_uint32(Object *obj, Visitor *v, const char *name,

> +                       void *opaque, Error **errp)

> +{

> +    Property *prop = opaque;

> +    uint32_t *ptr = object_field_prop_ptr(obj, prop);

> +

> +    visit_type_uint32(v, name, ptr, errp);

> +}

> +

> +static void set_uint32(Object *obj, Visitor *v, const char *name,

> +                       void *opaque, Error **errp)

> +{

> +    Property *prop = opaque;

> +    uint32_t *ptr = object_field_prop_ptr(obj, prop);

> +

> +    visit_type_uint32(v, name, ptr, errp);

> +}

> +

> +void field_prop_get_int32(Object *obj, Visitor *v, const char *name,

> +                          void *opaque, Error **errp)

> +{

> +    Property *prop = opaque;

> +    int32_t *ptr = object_field_prop_ptr(obj, prop);

> +

> +    visit_type_int32(v, name, ptr, errp);

> +}

> +

> +static void set_int32(Object *obj, Visitor *v, const char *name, void *opaque,

> +                      Error **errp)

> +{

> +    Property *prop = opaque;

> +    int32_t *ptr = object_field_prop_ptr(obj, prop);

> +

> +    visit_type_int32(v, name, ptr, errp);

> +}

> +

> +const PropertyInfo prop_info_uint32 = {

> +    .name  = "uint32",

> +    .get   = get_uint32,

> +    .set   = set_uint32,

> +    .set_default_value = field_prop_set_default_value_uint,

> +};

> +

> +const PropertyInfo prop_info_int32 = {

> +    .name  = "int32",

> +    .get   = field_prop_get_int32,

> +    .set   = set_int32,

> +    .set_default_value = field_prop_set_default_value_int,

> +};

> +

> +/* --- 64bit integer --- */

> +

> +static void get_uint64(Object *obj, Visitor *v, const char *name,

> +                       void *opaque, Error **errp)

> +{

> +    Property *prop = opaque;

> +    uint64_t *ptr = object_field_prop_ptr(obj, prop);

> +

> +    visit_type_uint64(v, name, ptr, errp);

> +}

> +

> +static void set_uint64(Object *obj, Visitor *v, const char *name,

> +                       void *opaque, Error **errp)

> +{

> +    Property *prop = opaque;

> +    uint64_t *ptr = object_field_prop_ptr(obj, prop);

> +

> +    visit_type_uint64(v, name, ptr, errp);

> +}

> +

> +static void get_int64(Object *obj, Visitor *v, const char *name,

> +                      void *opaque, Error **errp)

> +{

> +    Property *prop = opaque;

> +    int64_t *ptr = object_field_prop_ptr(obj, prop);

> +

> +    visit_type_int64(v, name, ptr, errp);

> +}

> +

> +static void set_int64(Object *obj, Visitor *v, const char *name,

> +                      void *opaque, Error **errp)

> +{

> +    Property *prop = opaque;

> +    int64_t *ptr = object_field_prop_ptr(obj, prop);

> +

> +    visit_type_int64(v, name, ptr, errp);

> +}

> +

> +const PropertyInfo prop_info_uint64 = {

> +    .name  = "uint64",

> +    .get   = get_uint64,

> +    .set   = set_uint64,

> +    .set_default_value = field_prop_set_default_value_uint,

> +};

> +

> +const PropertyInfo prop_info_int64 = {

> +    .name  = "int64",

> +    .get   = get_int64,

> +    .set   = set_int64,

> +    .set_default_value = field_prop_set_default_value_int,

> +};

> +

> +/* --- string --- */

> +

> +static void release_string(Object *obj, const char *name, void *opaque)

> +{

> +    Property *prop = opaque;

> +    g_free(*(char **)object_field_prop_ptr(obj, prop));

> +}

> +

> +static void get_string(Object *obj, Visitor *v, const char *name,

> +                       void *opaque, Error **errp)

> +{

> +    Property *prop = opaque;

> +    char **ptr = object_field_prop_ptr(obj, prop);

> +

> +    if (!*ptr) {

> +        char *str = (char *)"";

> +        visit_type_str(v, name, &str, errp);

> +    } else {

> +        visit_type_str(v, name, ptr, errp);

> +    }

> +}

> +

> +static void set_string(Object *obj, Visitor *v, const char *name,

> +                       void *opaque, Error **errp)

> +{

> +    Property *prop = opaque;

> +    char **ptr = object_field_prop_ptr(obj, prop);

> +    char *str;

> +

> +    if (!visit_type_str(v, name, &str, errp)) {

> +        return;

> +    }

> +    g_free(*ptr);

> +    *ptr = str;

> +}

> +

> +const PropertyInfo prop_info_string = {

> +    .name  = "str",

> +    .release = release_string,

> +    .get   = get_string,

> +    .set   = set_string,

> +};

> +

> +/* --- on/off/auto --- */

> +

> +const PropertyInfo prop_info_on_off_auto = {

> +    .name = "OnOffAuto",

> +    .description = "on/off/auto",

> +    .enum_table = &OnOffAuto_lookup,

> +    .get = field_prop_get_enum,

> +    .set = field_prop_set_enum,

> +    .set_default_value = field_prop_set_default_value_enum,

> +};

> +

> +/* --- 32bit unsigned int 'size' type --- */

> +

> +void field_prop_get_size32(Object *obj, Visitor *v, const char *name,

> +                           void *opaque, Error **errp)

> +{

> +    Property *prop = opaque;

> +    uint32_t *ptr = object_field_prop_ptr(obj, prop);

> +    uint64_t value = *ptr;

> +

> +    visit_type_size(v, name, &value, errp);

> +}

> +

> +static void set_size32(Object *obj, Visitor *v, const char *name, void *opaque,

> +                       Error **errp)

> +{

> +    Property *prop = opaque;

> +    uint32_t *ptr = object_field_prop_ptr(obj, prop);

> +    uint64_t value;

> +

> +    if (!visit_type_size(v, name, &value, errp)) {

> +        return;

> +    }

> +

> +    if (value > UINT32_MAX) {

> +        error_setg(errp,

> +                   "Property %s.%s doesn't take value %" PRIu64

> +                   " (maximum: %u)",

> +                   object_get_typename(obj), name, value, UINT32_MAX);

> +        return;

> +    }

> +

> +    *ptr = value;

> +}

> +

> +const PropertyInfo prop_info_size32 = {

> +    .name  = "size",

> +    .get = field_prop_get_size32,

> +    .set = set_size32,

> +    .set_default_value = field_prop_set_default_value_uint,

> +};

> +

> +/* --- support for array properties --- */

> +

> +static void set_prop_arraylen(Object *obj, Visitor *v, const char *name,

> +                              void *opaque, Error **errp)

> +{

> +    /* Setter for the property which defines the length of a

> +     * variable-sized property array. As well as actually setting the

> +     * array-length field in the device struct, we have to create the

> +     * array itself and dynamically add the corresponding properties.

> +     */

> +    Property *prop = opaque;

> +    ObjectProperty *op = object_property_find_err(obj, name, &error_abort);

> +    uint32_t *alenptr = object_field_prop_ptr(obj, prop);

> +    void **arrayptr = (void *)obj + prop->arrayoffset;

> +    void *eltptr;

> +    const char *arrayname;

> +    int i;

> +

> +    if (*alenptr) {

> +        error_setg(errp, "array size property %s may not be set more than once",

> +                   name);

> +        return;

> +    }

> +    if (!visit_type_uint32(v, name, alenptr, errp)) {

> +        return;

> +    }

> +    if (!*alenptr) {

> +        return;

> +    }

> +

> +    /* DEFINE_PROP_ARRAY guarantees that name should start with this prefix;

> +     * strip it off so we can get the name of the array itself.

> +     */

> +    assert(strncmp(name, PROP_ARRAY_LEN_PREFIX,

> +                   strlen(PROP_ARRAY_LEN_PREFIX)) == 0);

> +    arrayname = name + strlen(PROP_ARRAY_LEN_PREFIX);

> +

> +    /* Note that it is the responsibility of the individual device's deinit

> +     * to free the array proper.

> +     */

> +    *arrayptr = eltptr = g_malloc0(*alenptr * prop->arrayfieldsize);

> +    for (i = 0; i < *alenptr; i++, eltptr += prop->arrayfieldsize) {

> +        g_autofree char *propname = g_strdup_printf("%s[%d]", arrayname, i);

> +        Property *arrayprop = g_new0(Property, 1);

> +        arrayprop->info = prop->arrayinfo;

> +        /* This ugly piece of pointer arithmetic sets up the offset so

> +         * that when the underlying get/set hooks call qdev_get_prop_ptr

> +         * they get the right answer despite the array element not actually

> +         * being inside the device struct.

> +         */

> +        arrayprop->offset = eltptr - (void *)obj;

> +        assert(object_field_prop_ptr(obj, arrayprop) == eltptr);

> +        object_property_add_field(obj, propname, arrayprop, op->allow_set);

> +    }

> +}

> +

> +const PropertyInfo prop_info_arraylen = {

> +    .name = "uint32",

> +    .get = get_uint32,

> +    .set = set_prop_arraylen,

> +    .set_default_value = field_prop_set_default_value_uint,

> +};

> +

> +/* --- 64bit unsigned int 'size' type --- */

> +

> +static void get_size(Object *obj, Visitor *v, const char *name, void *opaque,

> +                     Error **errp)

> +{

> +    Property *prop = opaque;

> +    uint64_t *ptr = object_field_prop_ptr(obj, prop);

> +

> +    visit_type_size(v, name, ptr, errp);

> +}

> +

> +static void set_size(Object *obj, Visitor *v, const char *name, void *opaque,

> +                     Error **errp)

> +{

> +    Property *prop = opaque;

> +    uint64_t *ptr = object_field_prop_ptr(obj, prop);

> +

> +    visit_type_size(v, name, ptr, errp);

> +}

> +

> +const PropertyInfo prop_info_size = {

> +    .name  = "size",

> +    .get = get_size,

> +    .set = set_size,

> +    .set_default_value = field_prop_set_default_value_uint,

> +};

> +

> +/* --- object link property --- */

> +

> +static ObjectProperty *create_link_property(ObjectClass *oc, const char *name,

> +                                            Property *prop)

> +{

> +    /*

> +     * NOTE: object_property_allow_set_link is unconditional, but

> +     *       ObjectProperty.allow_set may be set for the property too.

> +     */

> +    return object_class_property_add_link(oc, name, prop->link_type,

> +                                          prop->offset,

> +                                          object_property_allow_set_link,

> +                                          OBJ_PROP_LINK_STRONG);

> +}

> +

> +const PropertyInfo prop_info_link = {

> +    .name = "link",

> +    .create = create_link_property,

> +};

> diff --git a/qom/meson.build b/qom/meson.build

> index e83794454d..7fdfd6fe7b 100644

> --- a/qom/meson.build

> +++ b/qom/meson.build

> @@ -5,6 +5,7 @@ qom_ss.add(files(

>     'object_interfaces.c',

>     'qom-qobject.c',

>     'field-property.c',

> +  'property-types.c',

>   ))

>   

>   qmp_ss.add(files('qom-qmp-cmds.c'))

>
Eduardo Habkost Nov. 4, 2020, 8:50 p.m. UTC | #2
On Wed, Nov 04, 2020 at 05:36:20PM +0100, Paolo Bonzini wrote:
> On 04/11/20 17:00, Eduardo Habkost wrote:

> > Move all property types from qdev-properties.c to

> > qom/property-types.c.

> > 

> > Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>

> > ---

> > Changes v1 -> v2:

> > * Rebased after changes in previous patches in the series

> > ---

> > Cc: Paolo Bonzini <pbonzini@redhat.com>

> > Cc: "Daniel P. Berrangé" <berrange@redhat.com>

> > Cc: Eduardo Habkost <ehabkost@redhat.com>

> > Cc: qemu-devel@nongnu.org

> > ---

> >   include/hw/qdev-properties.h | 179 +-----------

> >   include/qom/property-types.h | 185 ++++++++++++

> >   hw/core/qdev-properties.c    | 537 ----------------------------------

> >   qom/property-types.c         | 545 +++++++++++++++++++++++++++++++++++

> >   qom/meson.build              |   1 +

> >   5 files changed, 732 insertions(+), 715 deletions(-)

> >   create mode 100644 include/qom/property-types.h

> >   create mode 100644 qom/property-types.c

> 

> I would merge property-types.h and field-property.h in a single file.


I like keeping them separate, to force us to define the API used
to create new property types clearly.

What if I create a qom/qom.h header that includes object.h +
field-properties.h + property-types.h to make this easier to use?

> 

> Actually I wouldn't even bother having separate headers, however it's

> certainly valuable to have headers like you have in patch 42:

> 

> Core QOM API Reference

> ----------------------

> 

> ....

> 

> 

> Field Property API Reference

> ----------------------------

> 

> ....

> 

> 

> 

> I'm not sure if it's possible to include rST headers in .h files.


It is possible to include rST headers in doc comments, but the
way the DOC: blocks work in kernel-doc is weird and has subtle
rules and side effects.

> 

> Paolo

> 

> > diff --git a/include/hw/qdev-properties.h b/include/hw/qdev-properties.h

> > index bee26d0319..939b6dbf4e 100644

> > --- a/include/hw/qdev-properties.h

> > +++ b/include/hw/qdev-properties.h

> > @@ -3,184 +3,7 @@

> >   #include "hw/qdev-core.h"

> >   #include "qom/field-property.h"

> > -

> > -/*** qdev-properties.c ***/

> > -

> > -extern const PropertyInfo prop_info_bit;

> > -extern const PropertyInfo prop_info_bit64;

> > -extern const PropertyInfo prop_info_bool;

> > -extern const PropertyInfo prop_info_enum;

> > -extern const PropertyInfo prop_info_uint8;

> > -extern const PropertyInfo prop_info_uint16;

> > -extern const PropertyInfo prop_info_uint32;

> > -extern const PropertyInfo prop_info_int32;

> > -extern const PropertyInfo prop_info_uint64;

> > -extern const PropertyInfo prop_info_int64;

> > -extern const PropertyInfo prop_info_size;

> > -extern const PropertyInfo prop_info_string;

> > -extern const PropertyInfo prop_info_on_off_auto;

> > -extern const PropertyInfo prop_info_size32;

> > -extern const PropertyInfo prop_info_arraylen;

> > -extern const PropertyInfo prop_info_link;

> > -

> > -#define DEFINE_PROP(_name, _state, _field, _prop, _type, ...) {  \

> > -        .qdev_prop_name      = (_name),                          \

> > -        .info      = &(_prop),                                   \

> > -        .offset    = offsetof(_state, _field)                    \

> > -            + type_check(_type, typeof_field(_state, _field)),   \

> > -        __VA_ARGS__                                              \

> > -        }

> > -

> > -#define DEFINE_PROP_SIGNED(_name, _state, _field, _defval, _prop, _type) \

> > -    DEFINE_PROP(_name, _state, _field, _prop, _type,                     \

> > -                .set_default = true,                                     \

> > -                .defval.i    = (_type)_defval)

> > -

> > -#define DEFINE_PROP_SIGNED_NODEFAULT(_name, _state, _field, _prop, _type) \

> > -    DEFINE_PROP(_name, _state, _field, _prop, _type)

> > -

> > -#define DEFINE_PROP_BIT(_name, _state, _field, _bit, _defval)   \

> > -    DEFINE_PROP(_name, _state, _field, prop_info_bit, uint32_t, \

> > -                .bitnr       = (_bit),                          \

> > -                .set_default = true,                            \

> > -                .defval.u    = (bool)_defval)

> > -

> > -#define DEFINE_PROP_UNSIGNED(_name, _state, _field, _defval, _prop, _type) \

> > -    DEFINE_PROP(_name, _state, _field, _prop, _type,                       \

> > -                .set_default = true,                                       \

> > -                .defval.u  = (_type)_defval)

> > -

> > -#define DEFINE_PROP_UNSIGNED_NODEFAULT(_name, _state, _field, _prop, _type) \

> > -    DEFINE_PROP(_name, _state, _field, _prop, _type)

> > -

> > -#define DEFINE_PROP_BIT64(_name, _state, _field, _bit, _defval)   \

> > -    DEFINE_PROP(_name, _state, _field, prop_info_bit64, uint64_t, \

> > -                .bitnr    = (_bit),                               \

> > -                .set_default = true,                              \

> > -                .defval.u  = (bool)_defval)

> > -

> > -#define DEFINE_PROP_BOOL(_name, _state, _field, _defval)     \

> > -    DEFINE_PROP(_name, _state, _field, prop_info_bool, bool, \

> > -                .set_default = true,                         \

> > -                .defval.u    = (bool)_defval)

> > -

> > -#define PROP_ARRAY_LEN_PREFIX "len-"

> > -

> > -/**

> > - * DEFINE_PROP_ARRAY:

> > - * @_name: name of the array

> > - * @_state: name of the device state structure type

> > - * @_field: uint32_t field in @_state to hold the array length

> > - * @_arrayfield: field in @_state (of type '@_arraytype *') which

> > - *               will point to the array

> > - * @_arrayprop: PropertyInfo defining what property the array elements have

> > - * @_arraytype: C type of the array elements

> > - *

> > - * Define device properties for a variable-length array _name.  A

> > - * static property "len-arrayname" is defined. When the device creator

> > - * sets this property to the desired length of array, further dynamic

> > - * properties "arrayname[0]", "arrayname[1]", ...  are defined so the

> > - * device creator can set the array element values. Setting the

> > - * "len-arrayname" property more than once is an error.

> > - *

> > - * When the array length is set, the @_field member of the device

> > - * struct is set to the array length, and @_arrayfield is set to point

> > - * to (zero-initialised) memory allocated for the array.  For a zero

> > - * length array, @_field will be set to 0 and @_arrayfield to NULL.

> > - * It is the responsibility of the device deinit code to free the

> > - * @_arrayfield memory.

> > - */

> > -#define DEFINE_PROP_ARRAY(_name, _state, _field,               \

> > -                          _arrayfield, _arrayprop, _arraytype) \

> > -    DEFINE_PROP((PROP_ARRAY_LEN_PREFIX _name),                 \

> > -                _state, _field, prop_info_arraylen, uint32_t,  \

> > -                .set_default = true,                           \

> > -                .defval.u = 0,                                 \

> > -                .arrayinfo = &(_arrayprop),                    \

> > -                .arrayfieldsize = sizeof(_arraytype),          \

> > -                .arrayoffset = offsetof(_state, _arrayfield))

> > -

> > -#define DEFINE_PROP_LINK(_name, _state, _field, _type, _ptr_type)     \

> > -    DEFINE_PROP(_name, _state, _field, prop_info_link, _ptr_type,     \

> > -                .link_type  = _type)

> > -

> > -#define DEFINE_PROP_UINT8(_n, _s, _f, _d)                       \

> > -    DEFINE_PROP_UNSIGNED(_n, _s, _f, _d, prop_info_uint8, uint8_t)

> > -#define DEFINE_PROP_UINT16(_n, _s, _f, _d)                      \

> > -    DEFINE_PROP_UNSIGNED(_n, _s, _f, _d, prop_info_uint16, uint16_t)

> > -#define DEFINE_PROP_UINT32(_n, _s, _f, _d)                      \

> > -    DEFINE_PROP_UNSIGNED(_n, _s, _f, _d, prop_info_uint32, uint32_t)

> > -#define DEFINE_PROP_INT32(_n, _s, _f, _d)                      \

> > -    DEFINE_PROP_SIGNED(_n, _s, _f, _d, prop_info_int32, int32_t)

> > -#define DEFINE_PROP_UINT64(_n, _s, _f, _d)                      \

> > -    DEFINE_PROP_UNSIGNED(_n, _s, _f, _d, prop_info_uint64, uint64_t)

> > -#define DEFINE_PROP_INT64(_n, _s, _f, _d)                      \

> > -    DEFINE_PROP_SIGNED(_n, _s, _f, _d, prop_info_int64, int64_t)

> > -#define DEFINE_PROP_SIZE(_n, _s, _f, _d)                       \

> > -    DEFINE_PROP_UNSIGNED(_n, _s, _f, _d, prop_info_size, uint64_t)

> > -#define DEFINE_PROP_STRING(_n, _s, _f)             \

> > -    DEFINE_PROP(_n, _s, _f, prop_info_string, char*)

> > -#define DEFINE_PROP_ON_OFF_AUTO(_n, _s, _f, _d) \

> > -    DEFINE_PROP_SIGNED(_n, _s, _f, _d, prop_info_on_off_auto, OnOffAuto)

> > -#define DEFINE_PROP_SIZE32(_n, _s, _f, _d)                       \

> > -    DEFINE_PROP_UNSIGNED(_n, _s, _f, _d, prop_info_size32, uint32_t)

> > -

> > -#define DEFINE_PROP_END_OF_LIST()               \

> > -    {}

> > -

> > -/*

> > - * The PROP_* macros can be used as arguments for

> > - * object_class_property_add_field().  They will evaluate to a

> > - * pointer to a static variable.

> > - */

> > -

> > -#define FIELD_PROP(def) \

> > -    ({ static Property _p = def; &p; })

> > -

> > -#define PROP_SIGNED(...) \

> > -    FIELD_PROP(DEFINE_PROP_SIGNED(NULL, __VA_ARGS__))

> > -#define PROP_SIGNED_NODEFAULT(...) \

> > -    FIELD_PROP(DEFINE_PROP_SIGNED_NODEFAULT(NULL, __VA_ARGS__))

> > -#define PROP_BIT(...) \

> > -    FIELD_PROP(DEFINE_PROP_BIT(NULL, __VA_ARGS__))

> > -#define PROP_UNSIGNED(...) \

> > -    FIELD_PROP(DEFINE_PROP_UNSIGNED(NULL, __VA_ARGS__))

> > -#define PROP_UNSIGNED_NODEFAULT(...) \

> > -    FIELD_PROP(DEFINE_PROP_UNSIGNED_NODEFAULT(NULL, __VA_ARGS__))

> > -#define PROP_BIT64(...) \

> > -    FIELD_PROP(DEFINE_PROP_BIT64(NULL, __VA_ARGS__))

> > -#define PROP_BOOL(...) \

> > -    FIELD_PROP(DEFINE_PROP_BOOL(NULL, __VA_ARGS__))

> > -#define PROP_ARRAY(...) \

> > -    FIELD_PROP(DEFINE_PROP_ARRAY(NULL, __VA_ARGS__))

> > -#define PROP_LINK(...) \

> > -    FIELD_PROP(DEFINE_PROP_LINK(NULL, __VA_ARGS__))

> > -#define PROP_UINT8(...) \

> > -    FIELD_PROP(DEFINE_PROP_UINT8(NULL, __VA_ARGS__))

> > -#define PROP_UINT16(...) \

> > -    FIELD_PROP(DEFINE_PROP_UINT16(NULL, __VA_ARGS__))

> > -#define PROP_UINT32(...) \

> > -    FIELD_PROP(DEFINE_PROP_UINT32(NULL, __VA_ARGS__))

> > -#define PROP_INT32(...) \

> > -    FIELD_PROP(DEFINE_PROP_INT32(NULL, __VA_ARGS__))

> > -#define PROP_UINT64(...) \

> > -    FIELD_PROP(DEFINE_PROP_UINT64(NULL, __VA_ARGS__))

> > -#define PROP_INT64(...) \

> > -    FIELD_PROP(DEFINE_PROP_INT64(NULL, __VA_ARGS__))

> > -#define PROP_SIZE(...) \

> > -    FIELD_PROP(DEFINE_PROP_SIZE(NULL, __VA_ARGS__))

> > -#define PROP_STRING(...) \

> > -    FIELD_PROP(DEFINE_PROP_STRING(NULL, __VA_ARGS__))

> > -#define PROP_ON_OFF_AUTO(...) \

> > -    FIELD_PROP(DEFINE_PROP_ON_OFF_AUTO(NULL, __VA_ARGS__))

> > -#define PROP_SIZE32(...) \

> > -    FIELD_PROP(DEFINE_PROP_SIZE32(NULL, __VA_ARGS__))

> > -#define PROP_UUID(...) \

> > -    FIELD_PROP(DEFINE_PROP_UUID(NULL, __VA_ARGS__))

> > -#define PROP_UUID_NODEFAULT(...) \

> > -    FIELD_PROP(DEFINE_PROP_UUID_NODEFAULT(NULL, __VA_ARGS__))

> > -#define PROP_END_OF_LIST(...) \

> > -    FIELD_PROP(DEFINE_PROP_END_OF_LIST(NULL, __VA_ARGS__))

> > +#include "qom/property-types.h"

> >   /*

> >    * Set properties between creation and realization.

> > diff --git a/include/qom/property-types.h b/include/qom/property-types.h

> > new file mode 100644

> > index 0000000000..75f758e835

> > --- /dev/null

> > +++ b/include/qom/property-types.h

> > @@ -0,0 +1,185 @@

> > +/*

> > + * QOM field property types

> > + */

> > +#ifndef QOM_PROPERTY_TYPES_H

> > +#define QOM_PROPERTY_TYPES_H

> > +

> > +#include "qom/field-property.h"

> > +

> > +extern const PropertyInfo prop_info_bit;

> > +extern const PropertyInfo prop_info_bit64;

> > +extern const PropertyInfo prop_info_bool;

> > +extern const PropertyInfo prop_info_enum;

> > +extern const PropertyInfo prop_info_uint8;

> > +extern const PropertyInfo prop_info_uint16;

> > +extern const PropertyInfo prop_info_uint32;

> > +extern const PropertyInfo prop_info_int32;

> > +extern const PropertyInfo prop_info_uint64;

> > +extern const PropertyInfo prop_info_int64;

> > +extern const PropertyInfo prop_info_size;

> > +extern const PropertyInfo prop_info_string;

> > +extern const PropertyInfo prop_info_on_off_auto;

> > +extern const PropertyInfo prop_info_size32;

> > +extern const PropertyInfo prop_info_arraylen;

> > +extern const PropertyInfo prop_info_link;

> > +

> > +#define DEFINE_PROP(_name, _state, _field, _prop, _type, ...) {  \

> > +        .qdev_prop_name      = (_name),                          \

> > +        .info      = &(_prop),                                   \

> > +        .offset    = offsetof(_state, _field)                    \

> > +            + type_check(_type, typeof_field(_state, _field)),   \

> > +        __VA_ARGS__                                              \

> > +        }

> > +

> > +#define DEFINE_PROP_SIGNED(_name, _state, _field, _defval, _prop, _type) \

> > +    DEFINE_PROP(_name, _state, _field, _prop, _type,                     \

> > +                .set_default = true,                                     \

> > +                .defval.i    = (_type)_defval)

> > +

> > +#define DEFINE_PROP_SIGNED_NODEFAULT(_name, _state, _field, _prop, _type) \

> > +    DEFINE_PROP(_name, _state, _field, _prop, _type)

> > +

> > +#define DEFINE_PROP_BIT(_name, _state, _field, _bit, _defval)   \

> > +    DEFINE_PROP(_name, _state, _field, prop_info_bit, uint32_t, \

> > +                .bitnr       = (_bit),                          \

> > +                .set_default = true,                            \

> > +                .defval.u    = (bool)_defval)

> > +

> > +#define DEFINE_PROP_UNSIGNED(_name, _state, _field, _defval, _prop, _type) \

> > +    DEFINE_PROP(_name, _state, _field, _prop, _type,                       \

> > +                .set_default = true,                                       \

> > +                .defval.u  = (_type)_defval)

> > +

> > +#define DEFINE_PROP_UNSIGNED_NODEFAULT(_name, _state, _field, _prop, _type) \

> > +    DEFINE_PROP(_name, _state, _field, _prop, _type)

> > +

> > +#define DEFINE_PROP_BIT64(_name, _state, _field, _bit, _defval)   \

> > +    DEFINE_PROP(_name, _state, _field, prop_info_bit64, uint64_t, \

> > +                .bitnr    = (_bit),                               \

> > +                .set_default = true,                              \

> > +                .defval.u  = (bool)_defval)

> > +

> > +#define DEFINE_PROP_BOOL(_name, _state, _field, _defval)     \

> > +    DEFINE_PROP(_name, _state, _field, prop_info_bool, bool, \

> > +                .set_default = true,                         \

> > +                .defval.u    = (bool)_defval)

> > +

> > +#define PROP_ARRAY_LEN_PREFIX "len-"

> > +

> > +/**

> > + * DEFINE_PROP_ARRAY:

> > + * @_name: name of the array

> > + * @_state: name of the device state structure type

> > + * @_field: uint32_t field in @_state to hold the array length

> > + * @_arrayfield: field in @_state (of type '@_arraytype *') which

> > + *               will point to the array

> > + * @_arrayprop: PropertyInfo defining what property the array elements have

> > + * @_arraytype: C type of the array elements

> > + *

> > + * Define device properties for a variable-length array _name.  A

> > + * static property "len-arrayname" is defined. When the device creator

> > + * sets this property to the desired length of array, further dynamic

> > + * properties "arrayname[0]", "arrayname[1]", ...  are defined so the

> > + * device creator can set the array element values. Setting the

> > + * "len-arrayname" property more than once is an error.

> > + *

> > + * When the array length is set, the @_field member of the device

> > + * struct is set to the array length, and @_arrayfield is set to point

> > + * to (zero-initialised) memory allocated for the array.  For a zero

> > + * length array, @_field will be set to 0 and @_arrayfield to NULL.

> > + * It is the responsibility of the device deinit code to free the

> > + * @_arrayfield memory.

> > + */

> > +#define DEFINE_PROP_ARRAY(_name, _state, _field,               \

> > +                          _arrayfield, _arrayprop, _arraytype) \

> > +    DEFINE_PROP((PROP_ARRAY_LEN_PREFIX _name),                 \

> > +                _state, _field, prop_info_arraylen, uint32_t,  \

> > +                .set_default = true,                           \

> > +                .defval.u = 0,                                 \

> > +                .arrayinfo = &(_arrayprop),                    \

> > +                .arrayfieldsize = sizeof(_arraytype),          \

> > +                .arrayoffset = offsetof(_state, _arrayfield))

> > +

> > +#define DEFINE_PROP_LINK(_name, _state, _field, _type, _ptr_type)     \

> > +    DEFINE_PROP(_name, _state, _field, prop_info_link, _ptr_type,     \

> > +                .link_type  = _type)

> > +

> > +#define DEFINE_PROP_UINT8(_n, _s, _f, _d)                       \

> > +    DEFINE_PROP_UNSIGNED(_n, _s, _f, _d, prop_info_uint8, uint8_t)

> > +#define DEFINE_PROP_UINT16(_n, _s, _f, _d)                      \

> > +    DEFINE_PROP_UNSIGNED(_n, _s, _f, _d, prop_info_uint16, uint16_t)

> > +#define DEFINE_PROP_UINT32(_n, _s, _f, _d)                      \

> > +    DEFINE_PROP_UNSIGNED(_n, _s, _f, _d, prop_info_uint32, uint32_t)

> > +#define DEFINE_PROP_INT32(_n, _s, _f, _d)                      \

> > +    DEFINE_PROP_SIGNED(_n, _s, _f, _d, prop_info_int32, int32_t)

> > +#define DEFINE_PROP_UINT64(_n, _s, _f, _d)                      \

> > +    DEFINE_PROP_UNSIGNED(_n, _s, _f, _d, prop_info_uint64, uint64_t)

> > +#define DEFINE_PROP_INT64(_n, _s, _f, _d)                      \

> > +    DEFINE_PROP_SIGNED(_n, _s, _f, _d, prop_info_int64, int64_t)

> > +#define DEFINE_PROP_SIZE(_n, _s, _f, _d)                       \

> > +    DEFINE_PROP_UNSIGNED(_n, _s, _f, _d, prop_info_size, uint64_t)

> > +#define DEFINE_PROP_STRING(_n, _s, _f)             \

> > +    DEFINE_PROP(_n, _s, _f, prop_info_string, char*)

> > +#define DEFINE_PROP_ON_OFF_AUTO(_n, _s, _f, _d) \

> > +    DEFINE_PROP_SIGNED(_n, _s, _f, _d, prop_info_on_off_auto, OnOffAuto)

> > +#define DEFINE_PROP_SIZE32(_n, _s, _f, _d)                       \

> > +    DEFINE_PROP_UNSIGNED(_n, _s, _f, _d, prop_info_size32, uint32_t)

> > +

> > +#define DEFINE_PROP_END_OF_LIST()               \

> > +    {}

> > +

> > +/*

> > + * The PROP_* macros can be used as arguments for

> > + * object_class_property_add_field().  They will evaluate to a

> > + * pointer to a static variable.

> > + */

> > +

> > +#define FIELD_PROP(def) \

> > +    ({ static Property _p = def; &p; })

> > +

> > +#define PROP_SIGNED(...) \

> > +    FIELD_PROP(DEFINE_PROP_SIGNED(NULL, __VA_ARGS__))

> > +#define PROP_SIGNED_NODEFAULT(...) \

> > +    FIELD_PROP(DEFINE_PROP_SIGNED_NODEFAULT(NULL, __VA_ARGS__))

> > +#define PROP_BIT(...) \

> > +    FIELD_PROP(DEFINE_PROP_BIT(NULL, __VA_ARGS__))

> > +#define PROP_UNSIGNED(...) \

> > +    FIELD_PROP(DEFINE_PROP_UNSIGNED(NULL, __VA_ARGS__))

> > +#define PROP_UNSIGNED_NODEFAULT(...) \

> > +    FIELD_PROP(DEFINE_PROP_UNSIGNED_NODEFAULT(NULL, __VA_ARGS__))

> > +#define PROP_BIT64(...) \

> > +    FIELD_PROP(DEFINE_PROP_BIT64(NULL, __VA_ARGS__))

> > +#define PROP_BOOL(...) \

> > +    FIELD_PROP(DEFINE_PROP_BOOL(NULL, __VA_ARGS__))

> > +#define PROP_ARRAY(...) \

> > +    FIELD_PROP(DEFINE_PROP_ARRAY(NULL, __VA_ARGS__))

> > +#define PROP_LINK(...) \

> > +    FIELD_PROP(DEFINE_PROP_LINK(NULL, __VA_ARGS__))

> > +#define PROP_UINT8(...) \

> > +    FIELD_PROP(DEFINE_PROP_UINT8(NULL, __VA_ARGS__))

> > +#define PROP_UINT16(...) \

> > +    FIELD_PROP(DEFINE_PROP_UINT16(NULL, __VA_ARGS__))

> > +#define PROP_UINT32(...) \

> > +    FIELD_PROP(DEFINE_PROP_UINT32(NULL, __VA_ARGS__))

> > +#define PROP_INT32(...) \

> > +    FIELD_PROP(DEFINE_PROP_INT32(NULL, __VA_ARGS__))

> > +#define PROP_UINT64(...) \

> > +    FIELD_PROP(DEFINE_PROP_UINT64(NULL, __VA_ARGS__))

> > +#define PROP_INT64(...) \

> > +    FIELD_PROP(DEFINE_PROP_INT64(NULL, __VA_ARGS__))

> > +#define PROP_SIZE(...) \

> > +    FIELD_PROP(DEFINE_PROP_SIZE(NULL, __VA_ARGS__))

> > +#define PROP_STRING(...) \

> > +    FIELD_PROP(DEFINE_PROP_STRING(NULL, __VA_ARGS__))

> > +#define PROP_ON_OFF_AUTO(...) \

> > +    FIELD_PROP(DEFINE_PROP_ON_OFF_AUTO(NULL, __VA_ARGS__))

> > +#define PROP_SIZE32(...) \

> > +    FIELD_PROP(DEFINE_PROP_SIZE32(NULL, __VA_ARGS__))

> > +#define PROP_UUID(...) \

> > +    FIELD_PROP(DEFINE_PROP_UUID(NULL, __VA_ARGS__))

> > +#define PROP_UUID_NODEFAULT(...) \

> > +    FIELD_PROP(DEFINE_PROP_UUID_NODEFAULT(NULL, __VA_ARGS__))

> > +#define PROP_END_OF_LIST(...) \

> > +    FIELD_PROP(DEFINE_PROP_END_OF_LIST(NULL, __VA_ARGS__))

> > +

> > +#endif

> > diff --git a/hw/core/qdev-properties.c b/hw/core/qdev-properties.c

> > index b75730f15c..5bb4ff5f46 100644

> > --- a/hw/core/qdev-properties.c

> > +++ b/hw/core/qdev-properties.c

> > @@ -50,496 +50,6 @@ void qdev_prop_allow_set_link_before_realize(const Object *obj,

> >       }

> >   }

> > -void field_prop_get_enum(Object *obj, Visitor *v, const char *name,

> > -                         void *opaque, Error **errp)

> > -{

> > -    Property *prop = opaque;

> > -    int *ptr = object_field_prop_ptr(obj, prop);

> > -

> > -    visit_type_enum(v, name, ptr, prop->info->enum_table, errp);

> > -}

> > -

> > -void field_prop_set_enum(Object *obj, Visitor *v, const char *name,

> > -                         void *opaque, Error **errp)

> > -{

> > -    Property *prop = opaque;

> > -    int *ptr = object_field_prop_ptr(obj, prop);

> > -

> > -    visit_type_enum(v, name, ptr, prop->info->enum_table, errp);

> > -}

> > -

> > -void field_prop_set_default_value_enum(ObjectProperty *op,

> > -                                       const Property *prop)

> > -{

> > -    object_property_set_default_str(op,

> > -        qapi_enum_lookup(prop->info->enum_table, prop->defval.i));

> > -}

> > -

> > -const PropertyInfo prop_info_enum = {

> > -    .name  = "enum",

> > -    .get   = field_prop_get_enum,

> > -    .set   = field_prop_set_enum,

> > -    .set_default_value = field_prop_set_default_value_enum,

> > -};

> > -

> > -/* Bit */

> > -

> > -static uint32_t qdev_get_prop_mask(Property *prop)

> > -{

> > -    assert(prop->info == &prop_info_bit);

> > -    return 0x1 << prop->bitnr;

> > -}

> > -

> > -static void bit_prop_set(Object *obj, Property *props, bool val)

> > -{

> > -    uint32_t *p = object_field_prop_ptr(obj, props);

> > -    uint32_t mask = qdev_get_prop_mask(props);

> > -    if (val) {

> > -        *p |= mask;

> > -    } else {

> > -        *p &= ~mask;

> > -    }

> > -}

> > -

> > -static void prop_get_bit(Object *obj, Visitor *v, const char *name,

> > -                         void *opaque, Error **errp)

> > -{

> > -    Property *prop = opaque;

> > -    uint32_t *p = object_field_prop_ptr(obj, prop);

> > -    bool value = (*p & qdev_get_prop_mask(prop)) != 0;

> > -

> > -    visit_type_bool(v, name, &value, errp);

> > -}

> > -

> > -static void prop_set_bit(Object *obj, Visitor *v, const char *name,

> > -                         void *opaque, Error **errp)

> > -{

> > -    Property *prop = opaque;

> > -    bool value;

> > -

> > -    if (!visit_type_bool(v, name, &value, errp)) {

> > -        return;

> > -    }

> > -    bit_prop_set(obj, prop, value);

> > -}

> > -

> > -static void set_default_value_bool(ObjectProperty *op, const Property *prop)

> > -{

> > -    object_property_set_default_bool(op, prop->defval.u);

> > -}

> > -

> > -const PropertyInfo prop_info_bit = {

> > -    .name  = "bool",

> > -    .description = "on/off",

> > -    .get   = prop_get_bit,

> > -    .set   = prop_set_bit,

> > -    .set_default_value = set_default_value_bool,

> > -};

> > -

> > -/* Bit64 */

> > -

> > -static uint64_t qdev_get_prop_mask64(Property *prop)

> > -{

> > -    assert(prop->info == &prop_info_bit64);

> > -    return 0x1ull << prop->bitnr;

> > -}

> > -

> > -static void bit64_prop_set(Object *obj, Property *props, bool val)

> > -{

> > -    uint64_t *p = object_field_prop_ptr(obj, props);

> > -    uint64_t mask = qdev_get_prop_mask64(props);

> > -    if (val) {

> > -        *p |= mask;

> > -    } else {

> > -        *p &= ~mask;

> > -    }

> > -}

> > -

> > -static void prop_get_bit64(Object *obj, Visitor *v, const char *name,

> > -                           void *opaque, Error **errp)

> > -{

> > -    Property *prop = opaque;

> > -    uint64_t *p = object_field_prop_ptr(obj, prop);

> > -    bool value = (*p & qdev_get_prop_mask64(prop)) != 0;

> > -

> > -    visit_type_bool(v, name, &value, errp);

> > -}

> > -

> > -static void prop_set_bit64(Object *obj, Visitor *v, const char *name,

> > -                           void *opaque, Error **errp)

> > -{

> > -    Property *prop = opaque;

> > -    bool value;

> > -

> > -    if (!visit_type_bool(v, name, &value, errp)) {

> > -        return;

> > -    }

> > -    bit64_prop_set(obj, prop, value);

> > -}

> > -

> > -const PropertyInfo prop_info_bit64 = {

> > -    .name  = "bool",

> > -    .description = "on/off",

> > -    .get   = prop_get_bit64,

> > -    .set   = prop_set_bit64,

> > -    .set_default_value = set_default_value_bool,

> > -};

> > -

> > -/* --- bool --- */

> > -

> > -static void get_bool(Object *obj, Visitor *v, const char *name, void *opaque,

> > -                     Error **errp)

> > -{

> > -    Property *prop = opaque;

> > -    bool *ptr = object_field_prop_ptr(obj, prop);

> > -

> > -    visit_type_bool(v, name, ptr, errp);

> > -}

> > -

> > -static void set_bool(Object *obj, Visitor *v, const char *name, void *opaque,

> > -                     Error **errp)

> > -{

> > -    Property *prop = opaque;

> > -    bool *ptr = object_field_prop_ptr(obj, prop);

> > -

> > -    visit_type_bool(v, name, ptr, errp);

> > -}

> > -

> > -const PropertyInfo prop_info_bool = {

> > -    .name  = "bool",

> > -    .get   = get_bool,

> > -    .set   = set_bool,

> > -    .set_default_value = set_default_value_bool,

> > -};

> > -

> > -/* --- 8bit integer --- */

> > -

> > -static void get_uint8(Object *obj, Visitor *v, const char *name, void *opaque,

> > -                      Error **errp)

> > -{

> > -    Property *prop = opaque;

> > -    uint8_t *ptr = object_field_prop_ptr(obj, prop);

> > -

> > -    visit_type_uint8(v, name, ptr, errp);

> > -}

> > -

> > -static void set_uint8(Object *obj, Visitor *v, const char *name, void *opaque,

> > -                      Error **errp)

> > -{

> > -    Property *prop = opaque;

> > -    uint8_t *ptr = object_field_prop_ptr(obj, prop);

> > -

> > -    visit_type_uint8(v, name, ptr, errp);

> > -}

> > -

> > -void field_prop_set_default_value_int(ObjectProperty *op,

> > -                                      const Property *prop)

> > -{

> > -    object_property_set_default_int(op, prop->defval.i);

> > -}

> > -

> > -void field_prop_set_default_value_uint(ObjectProperty *op,

> > -                                       const Property *prop)

> > -{

> > -    object_property_set_default_uint(op, prop->defval.u);

> > -}

> > -

> > -const PropertyInfo prop_info_uint8 = {

> > -    .name  = "uint8",

> > -    .get   = get_uint8,

> > -    .set   = set_uint8,

> > -    .set_default_value = field_prop_set_default_value_uint,

> > -};

> > -

> > -/* --- 16bit integer --- */

> > -

> > -static void get_uint16(Object *obj, Visitor *v, const char *name,

> > -                       void *opaque, Error **errp)

> > -{

> > -    Property *prop = opaque;

> > -    uint16_t *ptr = object_field_prop_ptr(obj, prop);

> > -

> > -    visit_type_uint16(v, name, ptr, errp);

> > -}

> > -

> > -static void set_uint16(Object *obj, Visitor *v, const char *name,

> > -                       void *opaque, Error **errp)

> > -{

> > -    Property *prop = opaque;

> > -    uint16_t *ptr = object_field_prop_ptr(obj, prop);

> > -

> > -    visit_type_uint16(v, name, ptr, errp);

> > -}

> > -

> > -const PropertyInfo prop_info_uint16 = {

> > -    .name  = "uint16",

> > -    .get   = get_uint16,

> > -    .set   = set_uint16,

> > -    .set_default_value = field_prop_set_default_value_uint,

> > -};

> > -

> > -/* --- 32bit integer --- */

> > -

> > -static void get_uint32(Object *obj, Visitor *v, const char *name,

> > -                       void *opaque, Error **errp)

> > -{

> > -    Property *prop = opaque;

> > -    uint32_t *ptr = object_field_prop_ptr(obj, prop);

> > -

> > -    visit_type_uint32(v, name, ptr, errp);

> > -}

> > -

> > -static void set_uint32(Object *obj, Visitor *v, const char *name,

> > -                       void *opaque, Error **errp)

> > -{

> > -    Property *prop = opaque;

> > -    uint32_t *ptr = object_field_prop_ptr(obj, prop);

> > -

> > -    visit_type_uint32(v, name, ptr, errp);

> > -}

> > -

> > -void field_prop_get_int32(Object *obj, Visitor *v, const char *name,

> > -                          void *opaque, Error **errp)

> > -{

> > -    Property *prop = opaque;

> > -    int32_t *ptr = object_field_prop_ptr(obj, prop);

> > -

> > -    visit_type_int32(v, name, ptr, errp);

> > -}

> > -

> > -static void set_int32(Object *obj, Visitor *v, const char *name, void *opaque,

> > -                      Error **errp)

> > -{

> > -    Property *prop = opaque;

> > -    int32_t *ptr = object_field_prop_ptr(obj, prop);

> > -

> > -    visit_type_int32(v, name, ptr, errp);

> > -}

> > -

> > -const PropertyInfo prop_info_uint32 = {

> > -    .name  = "uint32",

> > -    .get   = get_uint32,

> > -    .set   = set_uint32,

> > -    .set_default_value = field_prop_set_default_value_uint,

> > -};

> > -

> > -const PropertyInfo prop_info_int32 = {

> > -    .name  = "int32",

> > -    .get   = field_prop_get_int32,

> > -    .set   = set_int32,

> > -    .set_default_value = field_prop_set_default_value_int,

> > -};

> > -

> > -/* --- 64bit integer --- */

> > -

> > -static void get_uint64(Object *obj, Visitor *v, const char *name,

> > -                       void *opaque, Error **errp)

> > -{

> > -    Property *prop = opaque;

> > -    uint64_t *ptr = object_field_prop_ptr(obj, prop);

> > -

> > -    visit_type_uint64(v, name, ptr, errp);

> > -}

> > -

> > -static void set_uint64(Object *obj, Visitor *v, const char *name,

> > -                       void *opaque, Error **errp)

> > -{

> > -    Property *prop = opaque;

> > -    uint64_t *ptr = object_field_prop_ptr(obj, prop);

> > -

> > -    visit_type_uint64(v, name, ptr, errp);

> > -}

> > -

> > -static void get_int64(Object *obj, Visitor *v, const char *name,

> > -                      void *opaque, Error **errp)

> > -{

> > -    Property *prop = opaque;

> > -    int64_t *ptr = object_field_prop_ptr(obj, prop);

> > -

> > -    visit_type_int64(v, name, ptr, errp);

> > -}

> > -

> > -static void set_int64(Object *obj, Visitor *v, const char *name,

> > -                      void *opaque, Error **errp)

> > -{

> > -    Property *prop = opaque;

> > -    int64_t *ptr = object_field_prop_ptr(obj, prop);

> > -

> > -    visit_type_int64(v, name, ptr, errp);

> > -}

> > -

> > -const PropertyInfo prop_info_uint64 = {

> > -    .name  = "uint64",

> > -    .get   = get_uint64,

> > -    .set   = set_uint64,

> > -    .set_default_value = field_prop_set_default_value_uint,

> > -};

> > -

> > -const PropertyInfo prop_info_int64 = {

> > -    .name  = "int64",

> > -    .get   = get_int64,

> > -    .set   = set_int64,

> > -    .set_default_value = field_prop_set_default_value_int,

> > -};

> > -

> > -/* --- string --- */

> > -

> > -static void release_string(Object *obj, const char *name, void *opaque)

> > -{

> > -    Property *prop = opaque;

> > -    g_free(*(char **)object_field_prop_ptr(obj, prop));

> > -}

> > -

> > -static void get_string(Object *obj, Visitor *v, const char *name,

> > -                       void *opaque, Error **errp)

> > -{

> > -    Property *prop = opaque;

> > -    char **ptr = object_field_prop_ptr(obj, prop);

> > -

> > -    if (!*ptr) {

> > -        char *str = (char *)"";

> > -        visit_type_str(v, name, &str, errp);

> > -    } else {

> > -        visit_type_str(v, name, ptr, errp);

> > -    }

> > -}

> > -

> > -static void set_string(Object *obj, Visitor *v, const char *name,

> > -                       void *opaque, Error **errp)

> > -{

> > -    Property *prop = opaque;

> > -    char **ptr = object_field_prop_ptr(obj, prop);

> > -    char *str;

> > -

> > -    if (!visit_type_str(v, name, &str, errp)) {

> > -        return;

> > -    }

> > -    g_free(*ptr);

> > -    *ptr = str;

> > -}

> > -

> > -const PropertyInfo prop_info_string = {

> > -    .name  = "str",

> > -    .release = release_string,

> > -    .get   = get_string,

> > -    .set   = set_string,

> > -};

> > -

> > -/* --- on/off/auto --- */

> > -

> > -const PropertyInfo prop_info_on_off_auto = {

> > -    .name = "OnOffAuto",

> > -    .description = "on/off/auto",

> > -    .enum_table = &OnOffAuto_lookup,

> > -    .get = field_prop_get_enum,

> > -    .set = field_prop_set_enum,

> > -    .set_default_value = field_prop_set_default_value_enum,

> > -};

> > -

> > -/* --- 32bit unsigned int 'size' type --- */

> > -

> > -void field_prop_get_size32(Object *obj, Visitor *v, const char *name,

> > -                           void *opaque, Error **errp)

> > -{

> > -    Property *prop = opaque;

> > -    uint32_t *ptr = object_field_prop_ptr(obj, prop);

> > -    uint64_t value = *ptr;

> > -

> > -    visit_type_size(v, name, &value, errp);

> > -}

> > -

> > -static void set_size32(Object *obj, Visitor *v, const char *name, void *opaque,

> > -                       Error **errp)

> > -{

> > -    Property *prop = opaque;

> > -    uint32_t *ptr = object_field_prop_ptr(obj, prop);

> > -    uint64_t value;

> > -

> > -    if (!visit_type_size(v, name, &value, errp)) {

> > -        return;

> > -    }

> > -

> > -    if (value > UINT32_MAX) {

> > -        error_setg(errp,

> > -                   "Property %s.%s doesn't take value %" PRIu64

> > -                   " (maximum: %u)",

> > -                   object_get_typename(obj), name, value, UINT32_MAX);

> > -        return;

> > -    }

> > -

> > -    *ptr = value;

> > -}

> > -

> > -const PropertyInfo prop_info_size32 = {

> > -    .name  = "size",

> > -    .get = field_prop_get_size32,

> > -    .set = set_size32,

> > -    .set_default_value = field_prop_set_default_value_uint,

> > -};

> > -

> > -/* --- support for array properties --- */

> > -

> > -static void set_prop_arraylen(Object *obj, Visitor *v, const char *name,

> > -                              void *opaque, Error **errp)

> > -{

> > -    /* Setter for the property which defines the length of a

> > -     * variable-sized property array. As well as actually setting the

> > -     * array-length field in the device struct, we have to create the

> > -     * array itself and dynamically add the corresponding properties.

> > -     */

> > -    Property *prop = opaque;

> > -    ObjectProperty *op = object_property_find_err(obj, name, &error_abort);

> > -    uint32_t *alenptr = object_field_prop_ptr(obj, prop);

> > -    void **arrayptr = (void *)obj + prop->arrayoffset;

> > -    void *eltptr;

> > -    const char *arrayname;

> > -    int i;

> > -

> > -    if (*alenptr) {

> > -        error_setg(errp, "array size property %s may not be set more than once",

> > -                   name);

> > -        return;

> > -    }

> > -    if (!visit_type_uint32(v, name, alenptr, errp)) {

> > -        return;

> > -    }

> > -    if (!*alenptr) {

> > -        return;

> > -    }

> > -

> > -    /* DEFINE_PROP_ARRAY guarantees that name should start with this prefix;

> > -     * strip it off so we can get the name of the array itself.

> > -     */

> > -    assert(strncmp(name, PROP_ARRAY_LEN_PREFIX,

> > -                   strlen(PROP_ARRAY_LEN_PREFIX)) == 0);

> > -    arrayname = name + strlen(PROP_ARRAY_LEN_PREFIX);

> > -

> > -    /* Note that it is the responsibility of the individual device's deinit

> > -     * to free the array proper.

> > -     */

> > -    *arrayptr = eltptr = g_malloc0(*alenptr * prop->arrayfieldsize);

> > -    for (i = 0; i < *alenptr; i++, eltptr += prop->arrayfieldsize) {

> > -        g_autofree char *propname = g_strdup_printf("%s[%d]", arrayname, i);

> > -        Property *arrayprop = g_new0(Property, 1);

> > -        arrayprop->info = prop->arrayinfo;

> > -        /* This ugly piece of pointer arithmetic sets up the offset so

> > -         * that when the underlying get/set hooks call qdev_get_prop_ptr

> > -         * they get the right answer despite the array element not actually

> > -         * being inside the device struct.

> > -         */

> > -        arrayprop->offset = eltptr - (void *)obj;

> > -        assert(object_field_prop_ptr(obj, arrayprop) == eltptr);

> > -        object_property_add_field(obj, propname, arrayprop, op->allow_set);

> > -    }

> > -}

> > -

> > -const PropertyInfo prop_info_arraylen = {

> > -    .name = "uint32",

> > -    .get = get_uint32,

> > -    .set = set_prop_arraylen,

> > -    .set_default_value = field_prop_set_default_value_uint,

> > -};

> > -

> >   /* --- public helpers --- */

> >   static Property *qdev_prop_walk(Property *props, const char *name)

> > @@ -712,53 +222,6 @@ void qdev_prop_set_globals(DeviceState *dev)

> >                                 dev->hotplugged ? NULL : &error_fatal);

> >   }

> > -/* --- 64bit unsigned int 'size' type --- */

> > -

> > -static void get_size(Object *obj, Visitor *v, const char *name, void *opaque,

> > -                     Error **errp)

> > -{

> > -    Property *prop = opaque;

> > -    uint64_t *ptr = object_field_prop_ptr(obj, prop);

> > -

> > -    visit_type_size(v, name, ptr, errp);

> > -}

> > -

> > -static void set_size(Object *obj, Visitor *v, const char *name, void *opaque,

> > -                     Error **errp)

> > -{

> > -    Property *prop = opaque;

> > -    uint64_t *ptr = object_field_prop_ptr(obj, prop);

> > -

> > -    visit_type_size(v, name, ptr, errp);

> > -}

> > -

> > -const PropertyInfo prop_info_size = {

> > -    .name  = "size",

> > -    .get = get_size,

> > -    .set = set_size,

> > -    .set_default_value = field_prop_set_default_value_uint,

> > -};

> > -

> > -/* --- object link property --- */

> > -

> > -static ObjectProperty *create_link_property(ObjectClass *oc, const char *name,

> > -                                            Property *prop)

> > -{

> > -    /*

> > -     * NOTE: object_property_allow_set_link is unconditional, but

> > -     *       ObjectProperty.allow_set may be set for the property too.

> > -     */

> > -    return object_class_property_add_link(oc, name, prop->link_type,

> > -                                          prop->offset,

> > -                                          object_property_allow_set_link,

> > -                                          OBJ_PROP_LINK_STRONG);

> > -}

> > -

> > -const PropertyInfo prop_info_link = {

> > -    .name = "link",

> > -    .create = create_link_property,

> > -};

> > -

> >   void qdev_property_add_static(DeviceState *dev, Property *prop)

> >   {

> >       object_property_add_field(OBJECT(dev), prop->qdev_prop_name, prop,

> > diff --git a/qom/property-types.c b/qom/property-types.c

> > new file mode 100644

> > index 0000000000..f566c05ec2

> > --- /dev/null

> > +++ b/qom/property-types.c

> > @@ -0,0 +1,545 @@

> > +#include "qemu/osdep.h"

> > +#include "qom/field-property.h"

> > +#include "qom/property-types.h"

> > +#include "qom/field-property-internal.h"

> > +#include "qapi/qapi-types-common.h"

> > +#include "qapi/visitor.h"

> > +#include "qapi/error.h"

> > +#include "qemu/uuid.h"

> > +

> > +void field_prop_get_enum(Object *obj, Visitor *v, const char *name,

> > +                         void *opaque, Error **errp)

> > +{

> > +    Property *prop = opaque;

> > +    int *ptr = object_field_prop_ptr(obj, prop);

> > +

> > +    visit_type_enum(v, name, ptr, prop->info->enum_table, errp);

> > +}

> > +

> > +void field_prop_set_enum(Object *obj, Visitor *v, const char *name,

> > +                         void *opaque, Error **errp)

> > +{

> > +    Property *prop = opaque;

> > +    int *ptr = object_field_prop_ptr(obj, prop);

> > +

> > +    visit_type_enum(v, name, ptr, prop->info->enum_table, errp);

> > +}

> > +

> > +void field_prop_set_default_value_enum(ObjectProperty *op,

> > +                                       const Property *prop)

> > +{

> > +    object_property_set_default_str(op,

> > +        qapi_enum_lookup(prop->info->enum_table, prop->defval.i));

> > +}

> > +

> > +const PropertyInfo prop_info_enum = {

> > +    .name  = "enum",

> > +    .get   = field_prop_get_enum,

> > +    .set   = field_prop_set_enum,

> > +    .set_default_value = field_prop_set_default_value_enum,

> > +};

> > +

> > +/* Bit */

> > +

> > +static uint32_t qdev_get_prop_mask(Property *prop)

> > +{

> > +    assert(prop->info == &prop_info_bit);

> > +    return 0x1 << prop->bitnr;

> > +}

> > +

> > +static void bit_prop_set(Object *obj, Property *props, bool val)

> > +{

> > +    uint32_t *p = object_field_prop_ptr(obj, props);

> > +    uint32_t mask = qdev_get_prop_mask(props);

> > +    if (val) {

> > +        *p |= mask;

> > +    } else {

> > +        *p &= ~mask;

> > +    }

> > +}

> > +

> > +static void prop_get_bit(Object *obj, Visitor *v, const char *name,

> > +                         void *opaque, Error **errp)

> > +{

> > +    Property *prop = opaque;

> > +    uint32_t *p = object_field_prop_ptr(obj, prop);

> > +    bool value = (*p & qdev_get_prop_mask(prop)) != 0;

> > +

> > +    visit_type_bool(v, name, &value, errp);

> > +}

> > +

> > +static void prop_set_bit(Object *obj, Visitor *v, const char *name,

> > +                         void *opaque, Error **errp)

> > +{

> > +    Property *prop = opaque;

> > +    bool value;

> > +

> > +    if (!visit_type_bool(v, name, &value, errp)) {

> > +        return;

> > +    }

> > +    bit_prop_set(obj, prop, value);

> > +}

> > +

> > +static void set_default_value_bool(ObjectProperty *op, const Property *prop)

> > +{

> > +    object_property_set_default_bool(op, prop->defval.u);

> > +}

> > +

> > +const PropertyInfo prop_info_bit = {

> > +    .name  = "bool",

> > +    .description = "on/off",

> > +    .get   = prop_get_bit,

> > +    .set   = prop_set_bit,

> > +    .set_default_value = set_default_value_bool,

> > +};

> > +

> > +/* Bit64 */

> > +

> > +static uint64_t qdev_get_prop_mask64(Property *prop)

> > +{

> > +    assert(prop->info == &prop_info_bit64);

> > +    return 0x1ull << prop->bitnr;

> > +}

> > +

> > +static void bit64_prop_set(Object *obj, Property *props, bool val)

> > +{

> > +    uint64_t *p = object_field_prop_ptr(obj, props);

> > +    uint64_t mask = qdev_get_prop_mask64(props);

> > +    if (val) {

> > +        *p |= mask;

> > +    } else {

> > +        *p &= ~mask;

> > +    }

> > +}

> > +

> > +static void prop_get_bit64(Object *obj, Visitor *v, const char *name,

> > +                           void *opaque, Error **errp)

> > +{

> > +    Property *prop = opaque;

> > +    uint64_t *p = object_field_prop_ptr(obj, prop);

> > +    bool value = (*p & qdev_get_prop_mask64(prop)) != 0;

> > +

> > +    visit_type_bool(v, name, &value, errp);

> > +}

> > +

> > +static void prop_set_bit64(Object *obj, Visitor *v, const char *name,

> > +                           void *opaque, Error **errp)

> > +{

> > +    Property *prop = opaque;

> > +    bool value;

> > +

> > +    if (!visit_type_bool(v, name, &value, errp)) {

> > +        return;

> > +    }

> > +    bit64_prop_set(obj, prop, value);

> > +}

> > +

> > +const PropertyInfo prop_info_bit64 = {

> > +    .name  = "bool",

> > +    .description = "on/off",

> > +    .get   = prop_get_bit64,

> > +    .set   = prop_set_bit64,

> > +    .set_default_value = set_default_value_bool,

> > +};

> > +

> > +/* --- bool --- */

> > +

> > +static void get_bool(Object *obj, Visitor *v, const char *name, void *opaque,

> > +                     Error **errp)

> > +{

> > +    Property *prop = opaque;

> > +    bool *ptr = object_field_prop_ptr(obj, prop);

> > +

> > +    visit_type_bool(v, name, ptr, errp);

> > +}

> > +

> > +static void set_bool(Object *obj, Visitor *v, const char *name, void *opaque,

> > +                     Error **errp)

> > +{

> > +    Property *prop = opaque;

> > +    bool *ptr = object_field_prop_ptr(obj, prop);

> > +

> > +    visit_type_bool(v, name, ptr, errp);

> > +}

> > +

> > +const PropertyInfo prop_info_bool = {

> > +    .name  = "bool",

> > +    .get   = get_bool,

> > +    .set   = set_bool,

> > +    .set_default_value = set_default_value_bool,

> > +};

> > +

> > +/* --- 8bit integer --- */

> > +

> > +static void get_uint8(Object *obj, Visitor *v, const char *name, void *opaque,

> > +                      Error **errp)

> > +{

> > +    Property *prop = opaque;

> > +    uint8_t *ptr = object_field_prop_ptr(obj, prop);

> > +

> > +    visit_type_uint8(v, name, ptr, errp);

> > +}

> > +

> > +static void set_uint8(Object *obj, Visitor *v, const char *name, void *opaque,

> > +                      Error **errp)

> > +{

> > +    Property *prop = opaque;

> > +    uint8_t *ptr = object_field_prop_ptr(obj, prop);

> > +

> > +    visit_type_uint8(v, name, ptr, errp);

> > +}

> > +

> > +void field_prop_set_default_value_int(ObjectProperty *op,

> > +                                      const Property *prop)

> > +{

> > +    object_property_set_default_int(op, prop->defval.i);

> > +}

> > +

> > +void field_prop_set_default_value_uint(ObjectProperty *op,

> > +                                       const Property *prop)

> > +{

> > +    object_property_set_default_uint(op, prop->defval.u);

> > +}

> > +

> > +const PropertyInfo prop_info_uint8 = {

> > +    .name  = "uint8",

> > +    .get   = get_uint8,

> > +    .set   = set_uint8,

> > +    .set_default_value = field_prop_set_default_value_uint,

> > +};

> > +

> > +/* --- 16bit integer --- */

> > +

> > +static void get_uint16(Object *obj, Visitor *v, const char *name,

> > +                       void *opaque, Error **errp)

> > +{

> > +    Property *prop = opaque;

> > +    uint16_t *ptr = object_field_prop_ptr(obj, prop);

> > +

> > +    visit_type_uint16(v, name, ptr, errp);

> > +}

> > +

> > +static void set_uint16(Object *obj, Visitor *v, const char *name,

> > +                       void *opaque, Error **errp)

> > +{

> > +    Property *prop = opaque;

> > +    uint16_t *ptr = object_field_prop_ptr(obj, prop);

> > +

> > +    visit_type_uint16(v, name, ptr, errp);

> > +}

> > +

> > +const PropertyInfo prop_info_uint16 = {

> > +    .name  = "uint16",

> > +    .get   = get_uint16,

> > +    .set   = set_uint16,

> > +    .set_default_value = field_prop_set_default_value_uint,

> > +};

> > +

> > +/* --- 32bit integer --- */

> > +

> > +static void get_uint32(Object *obj, Visitor *v, const char *name,

> > +                       void *opaque, Error **errp)

> > +{

> > +    Property *prop = opaque;

> > +    uint32_t *ptr = object_field_prop_ptr(obj, prop);

> > +

> > +    visit_type_uint32(v, name, ptr, errp);

> > +}

> > +

> > +static void set_uint32(Object *obj, Visitor *v, const char *name,

> > +                       void *opaque, Error **errp)

> > +{

> > +    Property *prop = opaque;

> > +    uint32_t *ptr = object_field_prop_ptr(obj, prop);

> > +

> > +    visit_type_uint32(v, name, ptr, errp);

> > +}

> > +

> > +void field_prop_get_int32(Object *obj, Visitor *v, const char *name,

> > +                          void *opaque, Error **errp)

> > +{

> > +    Property *prop = opaque;

> > +    int32_t *ptr = object_field_prop_ptr(obj, prop);

> > +

> > +    visit_type_int32(v, name, ptr, errp);

> > +}

> > +

> > +static void set_int32(Object *obj, Visitor *v, const char *name, void *opaque,

> > +                      Error **errp)

> > +{

> > +    Property *prop = opaque;

> > +    int32_t *ptr = object_field_prop_ptr(obj, prop);

> > +

> > +    visit_type_int32(v, name, ptr, errp);

> > +}

> > +

> > +const PropertyInfo prop_info_uint32 = {

> > +    .name  = "uint32",

> > +    .get   = get_uint32,

> > +    .set   = set_uint32,

> > +    .set_default_value = field_prop_set_default_value_uint,

> > +};

> > +

> > +const PropertyInfo prop_info_int32 = {

> > +    .name  = "int32",

> > +    .get   = field_prop_get_int32,

> > +    .set   = set_int32,

> > +    .set_default_value = field_prop_set_default_value_int,

> > +};

> > +

> > +/* --- 64bit integer --- */

> > +

> > +static void get_uint64(Object *obj, Visitor *v, const char *name,

> > +                       void *opaque, Error **errp)

> > +{

> > +    Property *prop = opaque;

> > +    uint64_t *ptr = object_field_prop_ptr(obj, prop);

> > +

> > +    visit_type_uint64(v, name, ptr, errp);

> > +}

> > +

> > +static void set_uint64(Object *obj, Visitor *v, const char *name,

> > +                       void *opaque, Error **errp)

> > +{

> > +    Property *prop = opaque;

> > +    uint64_t *ptr = object_field_prop_ptr(obj, prop);

> > +

> > +    visit_type_uint64(v, name, ptr, errp);

> > +}

> > +

> > +static void get_int64(Object *obj, Visitor *v, const char *name,

> > +                      void *opaque, Error **errp)

> > +{

> > +    Property *prop = opaque;

> > +    int64_t *ptr = object_field_prop_ptr(obj, prop);

> > +

> > +    visit_type_int64(v, name, ptr, errp);

> > +}

> > +

> > +static void set_int64(Object *obj, Visitor *v, const char *name,

> > +                      void *opaque, Error **errp)

> > +{

> > +    Property *prop = opaque;

> > +    int64_t *ptr = object_field_prop_ptr(obj, prop);

> > +

> > +    visit_type_int64(v, name, ptr, errp);

> > +}

> > +

> > +const PropertyInfo prop_info_uint64 = {

> > +    .name  = "uint64",

> > +    .get   = get_uint64,

> > +    .set   = set_uint64,

> > +    .set_default_value = field_prop_set_default_value_uint,

> > +};

> > +

> > +const PropertyInfo prop_info_int64 = {

> > +    .name  = "int64",

> > +    .get   = get_int64,

> > +    .set   = set_int64,

> > +    .set_default_value = field_prop_set_default_value_int,

> > +};

> > +

> > +/* --- string --- */

> > +

> > +static void release_string(Object *obj, const char *name, void *opaque)

> > +{

> > +    Property *prop = opaque;

> > +    g_free(*(char **)object_field_prop_ptr(obj, prop));

> > +}

> > +

> > +static void get_string(Object *obj, Visitor *v, const char *name,

> > +                       void *opaque, Error **errp)

> > +{

> > +    Property *prop = opaque;

> > +    char **ptr = object_field_prop_ptr(obj, prop);

> > +

> > +    if (!*ptr) {

> > +        char *str = (char *)"";

> > +        visit_type_str(v, name, &str, errp);

> > +    } else {

> > +        visit_type_str(v, name, ptr, errp);

> > +    }

> > +}

> > +

> > +static void set_string(Object *obj, Visitor *v, const char *name,

> > +                       void *opaque, Error **errp)

> > +{

> > +    Property *prop = opaque;

> > +    char **ptr = object_field_prop_ptr(obj, prop);

> > +    char *str;

> > +

> > +    if (!visit_type_str(v, name, &str, errp)) {

> > +        return;

> > +    }

> > +    g_free(*ptr);

> > +    *ptr = str;

> > +}

> > +

> > +const PropertyInfo prop_info_string = {

> > +    .name  = "str",

> > +    .release = release_string,

> > +    .get   = get_string,

> > +    .set   = set_string,

> > +};

> > +

> > +/* --- on/off/auto --- */

> > +

> > +const PropertyInfo prop_info_on_off_auto = {

> > +    .name = "OnOffAuto",

> > +    .description = "on/off/auto",

> > +    .enum_table = &OnOffAuto_lookup,

> > +    .get = field_prop_get_enum,

> > +    .set = field_prop_set_enum,

> > +    .set_default_value = field_prop_set_default_value_enum,

> > +};

> > +

> > +/* --- 32bit unsigned int 'size' type --- */

> > +

> > +void field_prop_get_size32(Object *obj, Visitor *v, const char *name,

> > +                           void *opaque, Error **errp)

> > +{

> > +    Property *prop = opaque;

> > +    uint32_t *ptr = object_field_prop_ptr(obj, prop);

> > +    uint64_t value = *ptr;

> > +

> > +    visit_type_size(v, name, &value, errp);

> > +}

> > +

> > +static void set_size32(Object *obj, Visitor *v, const char *name, void *opaque,

> > +                       Error **errp)

> > +{

> > +    Property *prop = opaque;

> > +    uint32_t *ptr = object_field_prop_ptr(obj, prop);

> > +    uint64_t value;

> > +

> > +    if (!visit_type_size(v, name, &value, errp)) {

> > +        return;

> > +    }

> > +

> > +    if (value > UINT32_MAX) {

> > +        error_setg(errp,

> > +                   "Property %s.%s doesn't take value %" PRIu64

> > +                   " (maximum: %u)",

> > +                   object_get_typename(obj), name, value, UINT32_MAX);

> > +        return;

> > +    }

> > +

> > +    *ptr = value;

> > +}

> > +

> > +const PropertyInfo prop_info_size32 = {

> > +    .name  = "size",

> > +    .get = field_prop_get_size32,

> > +    .set = set_size32,

> > +    .set_default_value = field_prop_set_default_value_uint,

> > +};

> > +

> > +/* --- support for array properties --- */

> > +

> > +static void set_prop_arraylen(Object *obj, Visitor *v, const char *name,

> > +                              void *opaque, Error **errp)

> > +{

> > +    /* Setter for the property which defines the length of a

> > +     * variable-sized property array. As well as actually setting the

> > +     * array-length field in the device struct, we have to create the

> > +     * array itself and dynamically add the corresponding properties.

> > +     */

> > +    Property *prop = opaque;

> > +    ObjectProperty *op = object_property_find_err(obj, name, &error_abort);

> > +    uint32_t *alenptr = object_field_prop_ptr(obj, prop);

> > +    void **arrayptr = (void *)obj + prop->arrayoffset;

> > +    void *eltptr;

> > +    const char *arrayname;

> > +    int i;

> > +

> > +    if (*alenptr) {

> > +        error_setg(errp, "array size property %s may not be set more than once",

> > +                   name);

> > +        return;

> > +    }

> > +    if (!visit_type_uint32(v, name, alenptr, errp)) {

> > +        return;

> > +    }

> > +    if (!*alenptr) {

> > +        return;

> > +    }

> > +

> > +    /* DEFINE_PROP_ARRAY guarantees that name should start with this prefix;

> > +     * strip it off so we can get the name of the array itself.

> > +     */

> > +    assert(strncmp(name, PROP_ARRAY_LEN_PREFIX,

> > +                   strlen(PROP_ARRAY_LEN_PREFIX)) == 0);

> > +    arrayname = name + strlen(PROP_ARRAY_LEN_PREFIX);

> > +

> > +    /* Note that it is the responsibility of the individual device's deinit

> > +     * to free the array proper.

> > +     */

> > +    *arrayptr = eltptr = g_malloc0(*alenptr * prop->arrayfieldsize);

> > +    for (i = 0; i < *alenptr; i++, eltptr += prop->arrayfieldsize) {

> > +        g_autofree char *propname = g_strdup_printf("%s[%d]", arrayname, i);

> > +        Property *arrayprop = g_new0(Property, 1);

> > +        arrayprop->info = prop->arrayinfo;

> > +        /* This ugly piece of pointer arithmetic sets up the offset so

> > +         * that when the underlying get/set hooks call qdev_get_prop_ptr

> > +         * they get the right answer despite the array element not actually

> > +         * being inside the device struct.

> > +         */

> > +        arrayprop->offset = eltptr - (void *)obj;

> > +        assert(object_field_prop_ptr(obj, arrayprop) == eltptr);

> > +        object_property_add_field(obj, propname, arrayprop, op->allow_set);

> > +    }

> > +}

> > +

> > +const PropertyInfo prop_info_arraylen = {

> > +    .name = "uint32",

> > +    .get = get_uint32,

> > +    .set = set_prop_arraylen,

> > +    .set_default_value = field_prop_set_default_value_uint,

> > +};

> > +

> > +/* --- 64bit unsigned int 'size' type --- */

> > +

> > +static void get_size(Object *obj, Visitor *v, const char *name, void *opaque,

> > +                     Error **errp)

> > +{

> > +    Property *prop = opaque;

> > +    uint64_t *ptr = object_field_prop_ptr(obj, prop);

> > +

> > +    visit_type_size(v, name, ptr, errp);

> > +}

> > +

> > +static void set_size(Object *obj, Visitor *v, const char *name, void *opaque,

> > +                     Error **errp)

> > +{

> > +    Property *prop = opaque;

> > +    uint64_t *ptr = object_field_prop_ptr(obj, prop);

> > +

> > +    visit_type_size(v, name, ptr, errp);

> > +}

> > +

> > +const PropertyInfo prop_info_size = {

> > +    .name  = "size",

> > +    .get = get_size,

> > +    .set = set_size,

> > +    .set_default_value = field_prop_set_default_value_uint,

> > +};

> > +

> > +/* --- object link property --- */

> > +

> > +static ObjectProperty *create_link_property(ObjectClass *oc, const char *name,

> > +                                            Property *prop)

> > +{

> > +    /*

> > +     * NOTE: object_property_allow_set_link is unconditional, but

> > +     *       ObjectProperty.allow_set may be set for the property too.

> > +     */

> > +    return object_class_property_add_link(oc, name, prop->link_type,

> > +                                          prop->offset,

> > +                                          object_property_allow_set_link,

> > +                                          OBJ_PROP_LINK_STRONG);

> > +}

> > +

> > +const PropertyInfo prop_info_link = {

> > +    .name = "link",

> > +    .create = create_link_property,

> > +};

> > diff --git a/qom/meson.build b/qom/meson.build

> > index e83794454d..7fdfd6fe7b 100644

> > --- a/qom/meson.build

> > +++ b/qom/meson.build

> > @@ -5,6 +5,7 @@ qom_ss.add(files(

> >     'object_interfaces.c',

> >     'qom-qobject.c',

> >     'field-property.c',

> > +  'property-types.c',

> >   ))

> >   qmp_ss.add(files('qom-qmp-cmds.c'))

> > 

> 


-- 
Eduardo
Paolo Bonzini Nov. 5, 2020, 9:36 a.m. UTC | #3
On 04/11/20 21:50, Eduardo Habkost wrote:
>> I would merge property-types.h and field-property.h in a single file.

> I like keeping them separate, to force us to define the API used

> to create new property types clearly.

> 

> What if I create a qom/qom.h header that includes object.h +

> field-properties.h + property-types.h to make this easier to use?

> 


Works for me!

Paolo
diff mbox series

Patch

diff --git a/include/hw/qdev-properties.h b/include/hw/qdev-properties.h
index bee26d0319..939b6dbf4e 100644
--- a/include/hw/qdev-properties.h
+++ b/include/hw/qdev-properties.h
@@ -3,184 +3,7 @@ 
 
 #include "hw/qdev-core.h"
 #include "qom/field-property.h"
-
-/*** qdev-properties.c ***/
-
-extern const PropertyInfo prop_info_bit;
-extern const PropertyInfo prop_info_bit64;
-extern const PropertyInfo prop_info_bool;
-extern const PropertyInfo prop_info_enum;
-extern const PropertyInfo prop_info_uint8;
-extern const PropertyInfo prop_info_uint16;
-extern const PropertyInfo prop_info_uint32;
-extern const PropertyInfo prop_info_int32;
-extern const PropertyInfo prop_info_uint64;
-extern const PropertyInfo prop_info_int64;
-extern const PropertyInfo prop_info_size;
-extern const PropertyInfo prop_info_string;
-extern const PropertyInfo prop_info_on_off_auto;
-extern const PropertyInfo prop_info_size32;
-extern const PropertyInfo prop_info_arraylen;
-extern const PropertyInfo prop_info_link;
-
-#define DEFINE_PROP(_name, _state, _field, _prop, _type, ...) {  \
-        .qdev_prop_name      = (_name),                          \
-        .info      = &(_prop),                                   \
-        .offset    = offsetof(_state, _field)                    \
-            + type_check(_type, typeof_field(_state, _field)),   \
-        __VA_ARGS__                                              \
-        }
-
-#define DEFINE_PROP_SIGNED(_name, _state, _field, _defval, _prop, _type) \
-    DEFINE_PROP(_name, _state, _field, _prop, _type,                     \
-                .set_default = true,                                     \
-                .defval.i    = (_type)_defval)
-
-#define DEFINE_PROP_SIGNED_NODEFAULT(_name, _state, _field, _prop, _type) \
-    DEFINE_PROP(_name, _state, _field, _prop, _type)
-
-#define DEFINE_PROP_BIT(_name, _state, _field, _bit, _defval)   \
-    DEFINE_PROP(_name, _state, _field, prop_info_bit, uint32_t, \
-                .bitnr       = (_bit),                          \
-                .set_default = true,                            \
-                .defval.u    = (bool)_defval)
-
-#define DEFINE_PROP_UNSIGNED(_name, _state, _field, _defval, _prop, _type) \
-    DEFINE_PROP(_name, _state, _field, _prop, _type,                       \
-                .set_default = true,                                       \
-                .defval.u  = (_type)_defval)
-
-#define DEFINE_PROP_UNSIGNED_NODEFAULT(_name, _state, _field, _prop, _type) \
-    DEFINE_PROP(_name, _state, _field, _prop, _type)
-
-#define DEFINE_PROP_BIT64(_name, _state, _field, _bit, _defval)   \
-    DEFINE_PROP(_name, _state, _field, prop_info_bit64, uint64_t, \
-                .bitnr    = (_bit),                               \
-                .set_default = true,                              \
-                .defval.u  = (bool)_defval)
-
-#define DEFINE_PROP_BOOL(_name, _state, _field, _defval)     \
-    DEFINE_PROP(_name, _state, _field, prop_info_bool, bool, \
-                .set_default = true,                         \
-                .defval.u    = (bool)_defval)
-
-#define PROP_ARRAY_LEN_PREFIX "len-"
-
-/**
- * DEFINE_PROP_ARRAY:
- * @_name: name of the array
- * @_state: name of the device state structure type
- * @_field: uint32_t field in @_state to hold the array length
- * @_arrayfield: field in @_state (of type '@_arraytype *') which
- *               will point to the array
- * @_arrayprop: PropertyInfo defining what property the array elements have
- * @_arraytype: C type of the array elements
- *
- * Define device properties for a variable-length array _name.  A
- * static property "len-arrayname" is defined. When the device creator
- * sets this property to the desired length of array, further dynamic
- * properties "arrayname[0]", "arrayname[1]", ...  are defined so the
- * device creator can set the array element values. Setting the
- * "len-arrayname" property more than once is an error.
- *
- * When the array length is set, the @_field member of the device
- * struct is set to the array length, and @_arrayfield is set to point
- * to (zero-initialised) memory allocated for the array.  For a zero
- * length array, @_field will be set to 0 and @_arrayfield to NULL.
- * It is the responsibility of the device deinit code to free the
- * @_arrayfield memory.
- */
-#define DEFINE_PROP_ARRAY(_name, _state, _field,               \
-                          _arrayfield, _arrayprop, _arraytype) \
-    DEFINE_PROP((PROP_ARRAY_LEN_PREFIX _name),                 \
-                _state, _field, prop_info_arraylen, uint32_t,  \
-                .set_default = true,                           \
-                .defval.u = 0,                                 \
-                .arrayinfo = &(_arrayprop),                    \
-                .arrayfieldsize = sizeof(_arraytype),          \
-                .arrayoffset = offsetof(_state, _arrayfield))
-
-#define DEFINE_PROP_LINK(_name, _state, _field, _type, _ptr_type)     \
-    DEFINE_PROP(_name, _state, _field, prop_info_link, _ptr_type,     \
-                .link_type  = _type)
-
-#define DEFINE_PROP_UINT8(_n, _s, _f, _d)                       \
-    DEFINE_PROP_UNSIGNED(_n, _s, _f, _d, prop_info_uint8, uint8_t)
-#define DEFINE_PROP_UINT16(_n, _s, _f, _d)                      \
-    DEFINE_PROP_UNSIGNED(_n, _s, _f, _d, prop_info_uint16, uint16_t)
-#define DEFINE_PROP_UINT32(_n, _s, _f, _d)                      \
-    DEFINE_PROP_UNSIGNED(_n, _s, _f, _d, prop_info_uint32, uint32_t)
-#define DEFINE_PROP_INT32(_n, _s, _f, _d)                      \
-    DEFINE_PROP_SIGNED(_n, _s, _f, _d, prop_info_int32, int32_t)
-#define DEFINE_PROP_UINT64(_n, _s, _f, _d)                      \
-    DEFINE_PROP_UNSIGNED(_n, _s, _f, _d, prop_info_uint64, uint64_t)
-#define DEFINE_PROP_INT64(_n, _s, _f, _d)                      \
-    DEFINE_PROP_SIGNED(_n, _s, _f, _d, prop_info_int64, int64_t)
-#define DEFINE_PROP_SIZE(_n, _s, _f, _d)                       \
-    DEFINE_PROP_UNSIGNED(_n, _s, _f, _d, prop_info_size, uint64_t)
-#define DEFINE_PROP_STRING(_n, _s, _f)             \
-    DEFINE_PROP(_n, _s, _f, prop_info_string, char*)
-#define DEFINE_PROP_ON_OFF_AUTO(_n, _s, _f, _d) \
-    DEFINE_PROP_SIGNED(_n, _s, _f, _d, prop_info_on_off_auto, OnOffAuto)
-#define DEFINE_PROP_SIZE32(_n, _s, _f, _d)                       \
-    DEFINE_PROP_UNSIGNED(_n, _s, _f, _d, prop_info_size32, uint32_t)
-
-#define DEFINE_PROP_END_OF_LIST()               \
-    {}
-
-/*
- * The PROP_* macros can be used as arguments for
- * object_class_property_add_field().  They will evaluate to a
- * pointer to a static variable.
- */
-
-#define FIELD_PROP(def) \
-    ({ static Property _p = def; &p; })
-
-#define PROP_SIGNED(...) \
-    FIELD_PROP(DEFINE_PROP_SIGNED(NULL, __VA_ARGS__))
-#define PROP_SIGNED_NODEFAULT(...) \
-    FIELD_PROP(DEFINE_PROP_SIGNED_NODEFAULT(NULL, __VA_ARGS__))
-#define PROP_BIT(...) \
-    FIELD_PROP(DEFINE_PROP_BIT(NULL, __VA_ARGS__))
-#define PROP_UNSIGNED(...) \
-    FIELD_PROP(DEFINE_PROP_UNSIGNED(NULL, __VA_ARGS__))
-#define PROP_UNSIGNED_NODEFAULT(...) \
-    FIELD_PROP(DEFINE_PROP_UNSIGNED_NODEFAULT(NULL, __VA_ARGS__))
-#define PROP_BIT64(...) \
-    FIELD_PROP(DEFINE_PROP_BIT64(NULL, __VA_ARGS__))
-#define PROP_BOOL(...) \
-    FIELD_PROP(DEFINE_PROP_BOOL(NULL, __VA_ARGS__))
-#define PROP_ARRAY(...) \
-    FIELD_PROP(DEFINE_PROP_ARRAY(NULL, __VA_ARGS__))
-#define PROP_LINK(...) \
-    FIELD_PROP(DEFINE_PROP_LINK(NULL, __VA_ARGS__))
-#define PROP_UINT8(...) \
-    FIELD_PROP(DEFINE_PROP_UINT8(NULL, __VA_ARGS__))
-#define PROP_UINT16(...) \
-    FIELD_PROP(DEFINE_PROP_UINT16(NULL, __VA_ARGS__))
-#define PROP_UINT32(...) \
-    FIELD_PROP(DEFINE_PROP_UINT32(NULL, __VA_ARGS__))
-#define PROP_INT32(...) \
-    FIELD_PROP(DEFINE_PROP_INT32(NULL, __VA_ARGS__))
-#define PROP_UINT64(...) \
-    FIELD_PROP(DEFINE_PROP_UINT64(NULL, __VA_ARGS__))
-#define PROP_INT64(...) \
-    FIELD_PROP(DEFINE_PROP_INT64(NULL, __VA_ARGS__))
-#define PROP_SIZE(...) \
-    FIELD_PROP(DEFINE_PROP_SIZE(NULL, __VA_ARGS__))
-#define PROP_STRING(...) \
-    FIELD_PROP(DEFINE_PROP_STRING(NULL, __VA_ARGS__))
-#define PROP_ON_OFF_AUTO(...) \
-    FIELD_PROP(DEFINE_PROP_ON_OFF_AUTO(NULL, __VA_ARGS__))
-#define PROP_SIZE32(...) \
-    FIELD_PROP(DEFINE_PROP_SIZE32(NULL, __VA_ARGS__))
-#define PROP_UUID(...) \
-    FIELD_PROP(DEFINE_PROP_UUID(NULL, __VA_ARGS__))
-#define PROP_UUID_NODEFAULT(...) \
-    FIELD_PROP(DEFINE_PROP_UUID_NODEFAULT(NULL, __VA_ARGS__))
-#define PROP_END_OF_LIST(...) \
-    FIELD_PROP(DEFINE_PROP_END_OF_LIST(NULL, __VA_ARGS__))
+#include "qom/property-types.h"
 
 /*
  * Set properties between creation and realization.
diff --git a/include/qom/property-types.h b/include/qom/property-types.h
new file mode 100644
index 0000000000..75f758e835
--- /dev/null
+++ b/include/qom/property-types.h
@@ -0,0 +1,185 @@ 
+/*
+ * QOM field property types
+ */
+#ifndef QOM_PROPERTY_TYPES_H
+#define QOM_PROPERTY_TYPES_H
+
+#include "qom/field-property.h"
+
+extern const PropertyInfo prop_info_bit;
+extern const PropertyInfo prop_info_bit64;
+extern const PropertyInfo prop_info_bool;
+extern const PropertyInfo prop_info_enum;
+extern const PropertyInfo prop_info_uint8;
+extern const PropertyInfo prop_info_uint16;
+extern const PropertyInfo prop_info_uint32;
+extern const PropertyInfo prop_info_int32;
+extern const PropertyInfo prop_info_uint64;
+extern const PropertyInfo prop_info_int64;
+extern const PropertyInfo prop_info_size;
+extern const PropertyInfo prop_info_string;
+extern const PropertyInfo prop_info_on_off_auto;
+extern const PropertyInfo prop_info_size32;
+extern const PropertyInfo prop_info_arraylen;
+extern const PropertyInfo prop_info_link;
+
+#define DEFINE_PROP(_name, _state, _field, _prop, _type, ...) {  \
+        .qdev_prop_name      = (_name),                          \
+        .info      = &(_prop),                                   \
+        .offset    = offsetof(_state, _field)                    \
+            + type_check(_type, typeof_field(_state, _field)),   \
+        __VA_ARGS__                                              \
+        }
+
+#define DEFINE_PROP_SIGNED(_name, _state, _field, _defval, _prop, _type) \
+    DEFINE_PROP(_name, _state, _field, _prop, _type,                     \
+                .set_default = true,                                     \
+                .defval.i    = (_type)_defval)
+
+#define DEFINE_PROP_SIGNED_NODEFAULT(_name, _state, _field, _prop, _type) \
+    DEFINE_PROP(_name, _state, _field, _prop, _type)
+
+#define DEFINE_PROP_BIT(_name, _state, _field, _bit, _defval)   \
+    DEFINE_PROP(_name, _state, _field, prop_info_bit, uint32_t, \
+                .bitnr       = (_bit),                          \
+                .set_default = true,                            \
+                .defval.u    = (bool)_defval)
+
+#define DEFINE_PROP_UNSIGNED(_name, _state, _field, _defval, _prop, _type) \
+    DEFINE_PROP(_name, _state, _field, _prop, _type,                       \
+                .set_default = true,                                       \
+                .defval.u  = (_type)_defval)
+
+#define DEFINE_PROP_UNSIGNED_NODEFAULT(_name, _state, _field, _prop, _type) \
+    DEFINE_PROP(_name, _state, _field, _prop, _type)
+
+#define DEFINE_PROP_BIT64(_name, _state, _field, _bit, _defval)   \
+    DEFINE_PROP(_name, _state, _field, prop_info_bit64, uint64_t, \
+                .bitnr    = (_bit),                               \
+                .set_default = true,                              \
+                .defval.u  = (bool)_defval)
+
+#define DEFINE_PROP_BOOL(_name, _state, _field, _defval)     \
+    DEFINE_PROP(_name, _state, _field, prop_info_bool, bool, \
+                .set_default = true,                         \
+                .defval.u    = (bool)_defval)
+
+#define PROP_ARRAY_LEN_PREFIX "len-"
+
+/**
+ * DEFINE_PROP_ARRAY:
+ * @_name: name of the array
+ * @_state: name of the device state structure type
+ * @_field: uint32_t field in @_state to hold the array length
+ * @_arrayfield: field in @_state (of type '@_arraytype *') which
+ *               will point to the array
+ * @_arrayprop: PropertyInfo defining what property the array elements have
+ * @_arraytype: C type of the array elements
+ *
+ * Define device properties for a variable-length array _name.  A
+ * static property "len-arrayname" is defined. When the device creator
+ * sets this property to the desired length of array, further dynamic
+ * properties "arrayname[0]", "arrayname[1]", ...  are defined so the
+ * device creator can set the array element values. Setting the
+ * "len-arrayname" property more than once is an error.
+ *
+ * When the array length is set, the @_field member of the device
+ * struct is set to the array length, and @_arrayfield is set to point
+ * to (zero-initialised) memory allocated for the array.  For a zero
+ * length array, @_field will be set to 0 and @_arrayfield to NULL.
+ * It is the responsibility of the device deinit code to free the
+ * @_arrayfield memory.
+ */
+#define DEFINE_PROP_ARRAY(_name, _state, _field,               \
+                          _arrayfield, _arrayprop, _arraytype) \
+    DEFINE_PROP((PROP_ARRAY_LEN_PREFIX _name),                 \
+                _state, _field, prop_info_arraylen, uint32_t,  \
+                .set_default = true,                           \
+                .defval.u = 0,                                 \
+                .arrayinfo = &(_arrayprop),                    \
+                .arrayfieldsize = sizeof(_arraytype),          \
+                .arrayoffset = offsetof(_state, _arrayfield))
+
+#define DEFINE_PROP_LINK(_name, _state, _field, _type, _ptr_type)     \
+    DEFINE_PROP(_name, _state, _field, prop_info_link, _ptr_type,     \
+                .link_type  = _type)
+
+#define DEFINE_PROP_UINT8(_n, _s, _f, _d)                       \
+    DEFINE_PROP_UNSIGNED(_n, _s, _f, _d, prop_info_uint8, uint8_t)
+#define DEFINE_PROP_UINT16(_n, _s, _f, _d)                      \
+    DEFINE_PROP_UNSIGNED(_n, _s, _f, _d, prop_info_uint16, uint16_t)
+#define DEFINE_PROP_UINT32(_n, _s, _f, _d)                      \
+    DEFINE_PROP_UNSIGNED(_n, _s, _f, _d, prop_info_uint32, uint32_t)
+#define DEFINE_PROP_INT32(_n, _s, _f, _d)                      \
+    DEFINE_PROP_SIGNED(_n, _s, _f, _d, prop_info_int32, int32_t)
+#define DEFINE_PROP_UINT64(_n, _s, _f, _d)                      \
+    DEFINE_PROP_UNSIGNED(_n, _s, _f, _d, prop_info_uint64, uint64_t)
+#define DEFINE_PROP_INT64(_n, _s, _f, _d)                      \
+    DEFINE_PROP_SIGNED(_n, _s, _f, _d, prop_info_int64, int64_t)
+#define DEFINE_PROP_SIZE(_n, _s, _f, _d)                       \
+    DEFINE_PROP_UNSIGNED(_n, _s, _f, _d, prop_info_size, uint64_t)
+#define DEFINE_PROP_STRING(_n, _s, _f)             \
+    DEFINE_PROP(_n, _s, _f, prop_info_string, char*)
+#define DEFINE_PROP_ON_OFF_AUTO(_n, _s, _f, _d) \
+    DEFINE_PROP_SIGNED(_n, _s, _f, _d, prop_info_on_off_auto, OnOffAuto)
+#define DEFINE_PROP_SIZE32(_n, _s, _f, _d)                       \
+    DEFINE_PROP_UNSIGNED(_n, _s, _f, _d, prop_info_size32, uint32_t)
+
+#define DEFINE_PROP_END_OF_LIST()               \
+    {}
+
+/*
+ * The PROP_* macros can be used as arguments for
+ * object_class_property_add_field().  They will evaluate to a
+ * pointer to a static variable.
+ */
+
+#define FIELD_PROP(def) \
+    ({ static Property _p = def; &p; })
+
+#define PROP_SIGNED(...) \
+    FIELD_PROP(DEFINE_PROP_SIGNED(NULL, __VA_ARGS__))
+#define PROP_SIGNED_NODEFAULT(...) \
+    FIELD_PROP(DEFINE_PROP_SIGNED_NODEFAULT(NULL, __VA_ARGS__))
+#define PROP_BIT(...) \
+    FIELD_PROP(DEFINE_PROP_BIT(NULL, __VA_ARGS__))
+#define PROP_UNSIGNED(...) \
+    FIELD_PROP(DEFINE_PROP_UNSIGNED(NULL, __VA_ARGS__))
+#define PROP_UNSIGNED_NODEFAULT(...) \
+    FIELD_PROP(DEFINE_PROP_UNSIGNED_NODEFAULT(NULL, __VA_ARGS__))
+#define PROP_BIT64(...) \
+    FIELD_PROP(DEFINE_PROP_BIT64(NULL, __VA_ARGS__))
+#define PROP_BOOL(...) \
+    FIELD_PROP(DEFINE_PROP_BOOL(NULL, __VA_ARGS__))
+#define PROP_ARRAY(...) \
+    FIELD_PROP(DEFINE_PROP_ARRAY(NULL, __VA_ARGS__))
+#define PROP_LINK(...) \
+    FIELD_PROP(DEFINE_PROP_LINK(NULL, __VA_ARGS__))
+#define PROP_UINT8(...) \
+    FIELD_PROP(DEFINE_PROP_UINT8(NULL, __VA_ARGS__))
+#define PROP_UINT16(...) \
+    FIELD_PROP(DEFINE_PROP_UINT16(NULL, __VA_ARGS__))
+#define PROP_UINT32(...) \
+    FIELD_PROP(DEFINE_PROP_UINT32(NULL, __VA_ARGS__))
+#define PROP_INT32(...) \
+    FIELD_PROP(DEFINE_PROP_INT32(NULL, __VA_ARGS__))
+#define PROP_UINT64(...) \
+    FIELD_PROP(DEFINE_PROP_UINT64(NULL, __VA_ARGS__))
+#define PROP_INT64(...) \
+    FIELD_PROP(DEFINE_PROP_INT64(NULL, __VA_ARGS__))
+#define PROP_SIZE(...) \
+    FIELD_PROP(DEFINE_PROP_SIZE(NULL, __VA_ARGS__))
+#define PROP_STRING(...) \
+    FIELD_PROP(DEFINE_PROP_STRING(NULL, __VA_ARGS__))
+#define PROP_ON_OFF_AUTO(...) \
+    FIELD_PROP(DEFINE_PROP_ON_OFF_AUTO(NULL, __VA_ARGS__))
+#define PROP_SIZE32(...) \
+    FIELD_PROP(DEFINE_PROP_SIZE32(NULL, __VA_ARGS__))
+#define PROP_UUID(...) \
+    FIELD_PROP(DEFINE_PROP_UUID(NULL, __VA_ARGS__))
+#define PROP_UUID_NODEFAULT(...) \
+    FIELD_PROP(DEFINE_PROP_UUID_NODEFAULT(NULL, __VA_ARGS__))
+#define PROP_END_OF_LIST(...) \
+    FIELD_PROP(DEFINE_PROP_END_OF_LIST(NULL, __VA_ARGS__))
+
+#endif
diff --git a/hw/core/qdev-properties.c b/hw/core/qdev-properties.c
index b75730f15c..5bb4ff5f46 100644
--- a/hw/core/qdev-properties.c
+++ b/hw/core/qdev-properties.c
@@ -50,496 +50,6 @@  void qdev_prop_allow_set_link_before_realize(const Object *obj,
     }
 }
 
-void field_prop_get_enum(Object *obj, Visitor *v, const char *name,
-                         void *opaque, Error **errp)
-{
-    Property *prop = opaque;
-    int *ptr = object_field_prop_ptr(obj, prop);
-
-    visit_type_enum(v, name, ptr, prop->info->enum_table, errp);
-}
-
-void field_prop_set_enum(Object *obj, Visitor *v, const char *name,
-                         void *opaque, Error **errp)
-{
-    Property *prop = opaque;
-    int *ptr = object_field_prop_ptr(obj, prop);
-
-    visit_type_enum(v, name, ptr, prop->info->enum_table, errp);
-}
-
-void field_prop_set_default_value_enum(ObjectProperty *op,
-                                       const Property *prop)
-{
-    object_property_set_default_str(op,
-        qapi_enum_lookup(prop->info->enum_table, prop->defval.i));
-}
-
-const PropertyInfo prop_info_enum = {
-    .name  = "enum",
-    .get   = field_prop_get_enum,
-    .set   = field_prop_set_enum,
-    .set_default_value = field_prop_set_default_value_enum,
-};
-
-/* Bit */
-
-static uint32_t qdev_get_prop_mask(Property *prop)
-{
-    assert(prop->info == &prop_info_bit);
-    return 0x1 << prop->bitnr;
-}
-
-static void bit_prop_set(Object *obj, Property *props, bool val)
-{
-    uint32_t *p = object_field_prop_ptr(obj, props);
-    uint32_t mask = qdev_get_prop_mask(props);
-    if (val) {
-        *p |= mask;
-    } else {
-        *p &= ~mask;
-    }
-}
-
-static void prop_get_bit(Object *obj, Visitor *v, const char *name,
-                         void *opaque, Error **errp)
-{
-    Property *prop = opaque;
-    uint32_t *p = object_field_prop_ptr(obj, prop);
-    bool value = (*p & qdev_get_prop_mask(prop)) != 0;
-
-    visit_type_bool(v, name, &value, errp);
-}
-
-static void prop_set_bit(Object *obj, Visitor *v, const char *name,
-                         void *opaque, Error **errp)
-{
-    Property *prop = opaque;
-    bool value;
-
-    if (!visit_type_bool(v, name, &value, errp)) {
-        return;
-    }
-    bit_prop_set(obj, prop, value);
-}
-
-static void set_default_value_bool(ObjectProperty *op, const Property *prop)
-{
-    object_property_set_default_bool(op, prop->defval.u);
-}
-
-const PropertyInfo prop_info_bit = {
-    .name  = "bool",
-    .description = "on/off",
-    .get   = prop_get_bit,
-    .set   = prop_set_bit,
-    .set_default_value = set_default_value_bool,
-};
-
-/* Bit64 */
-
-static uint64_t qdev_get_prop_mask64(Property *prop)
-{
-    assert(prop->info == &prop_info_bit64);
-    return 0x1ull << prop->bitnr;
-}
-
-static void bit64_prop_set(Object *obj, Property *props, bool val)
-{
-    uint64_t *p = object_field_prop_ptr(obj, props);
-    uint64_t mask = qdev_get_prop_mask64(props);
-    if (val) {
-        *p |= mask;
-    } else {
-        *p &= ~mask;
-    }
-}
-
-static void prop_get_bit64(Object *obj, Visitor *v, const char *name,
-                           void *opaque, Error **errp)
-{
-    Property *prop = opaque;
-    uint64_t *p = object_field_prop_ptr(obj, prop);
-    bool value = (*p & qdev_get_prop_mask64(prop)) != 0;
-
-    visit_type_bool(v, name, &value, errp);
-}
-
-static void prop_set_bit64(Object *obj, Visitor *v, const char *name,
-                           void *opaque, Error **errp)
-{
-    Property *prop = opaque;
-    bool value;
-
-    if (!visit_type_bool(v, name, &value, errp)) {
-        return;
-    }
-    bit64_prop_set(obj, prop, value);
-}
-
-const PropertyInfo prop_info_bit64 = {
-    .name  = "bool",
-    .description = "on/off",
-    .get   = prop_get_bit64,
-    .set   = prop_set_bit64,
-    .set_default_value = set_default_value_bool,
-};
-
-/* --- bool --- */
-
-static void get_bool(Object *obj, Visitor *v, const char *name, void *opaque,
-                     Error **errp)
-{
-    Property *prop = opaque;
-    bool *ptr = object_field_prop_ptr(obj, prop);
-
-    visit_type_bool(v, name, ptr, errp);
-}
-
-static void set_bool(Object *obj, Visitor *v, const char *name, void *opaque,
-                     Error **errp)
-{
-    Property *prop = opaque;
-    bool *ptr = object_field_prop_ptr(obj, prop);
-
-    visit_type_bool(v, name, ptr, errp);
-}
-
-const PropertyInfo prop_info_bool = {
-    .name  = "bool",
-    .get   = get_bool,
-    .set   = set_bool,
-    .set_default_value = set_default_value_bool,
-};
-
-/* --- 8bit integer --- */
-
-static void get_uint8(Object *obj, Visitor *v, const char *name, void *opaque,
-                      Error **errp)
-{
-    Property *prop = opaque;
-    uint8_t *ptr = object_field_prop_ptr(obj, prop);
-
-    visit_type_uint8(v, name, ptr, errp);
-}
-
-static void set_uint8(Object *obj, Visitor *v, const char *name, void *opaque,
-                      Error **errp)
-{
-    Property *prop = opaque;
-    uint8_t *ptr = object_field_prop_ptr(obj, prop);
-
-    visit_type_uint8(v, name, ptr, errp);
-}
-
-void field_prop_set_default_value_int(ObjectProperty *op,
-                                      const Property *prop)
-{
-    object_property_set_default_int(op, prop->defval.i);
-}
-
-void field_prop_set_default_value_uint(ObjectProperty *op,
-                                       const Property *prop)
-{
-    object_property_set_default_uint(op, prop->defval.u);
-}
-
-const PropertyInfo prop_info_uint8 = {
-    .name  = "uint8",
-    .get   = get_uint8,
-    .set   = set_uint8,
-    .set_default_value = field_prop_set_default_value_uint,
-};
-
-/* --- 16bit integer --- */
-
-static void get_uint16(Object *obj, Visitor *v, const char *name,
-                       void *opaque, Error **errp)
-{
-    Property *prop = opaque;
-    uint16_t *ptr = object_field_prop_ptr(obj, prop);
-
-    visit_type_uint16(v, name, ptr, errp);
-}
-
-static void set_uint16(Object *obj, Visitor *v, const char *name,
-                       void *opaque, Error **errp)
-{
-    Property *prop = opaque;
-    uint16_t *ptr = object_field_prop_ptr(obj, prop);
-
-    visit_type_uint16(v, name, ptr, errp);
-}
-
-const PropertyInfo prop_info_uint16 = {
-    .name  = "uint16",
-    .get   = get_uint16,
-    .set   = set_uint16,
-    .set_default_value = field_prop_set_default_value_uint,
-};
-
-/* --- 32bit integer --- */
-
-static void get_uint32(Object *obj, Visitor *v, const char *name,
-                       void *opaque, Error **errp)
-{
-    Property *prop = opaque;
-    uint32_t *ptr = object_field_prop_ptr(obj, prop);
-
-    visit_type_uint32(v, name, ptr, errp);
-}
-
-static void set_uint32(Object *obj, Visitor *v, const char *name,
-                       void *opaque, Error **errp)
-{
-    Property *prop = opaque;
-    uint32_t *ptr = object_field_prop_ptr(obj, prop);
-
-    visit_type_uint32(v, name, ptr, errp);
-}
-
-void field_prop_get_int32(Object *obj, Visitor *v, const char *name,
-                          void *opaque, Error **errp)
-{
-    Property *prop = opaque;
-    int32_t *ptr = object_field_prop_ptr(obj, prop);
-
-    visit_type_int32(v, name, ptr, errp);
-}
-
-static void set_int32(Object *obj, Visitor *v, const char *name, void *opaque,
-                      Error **errp)
-{
-    Property *prop = opaque;
-    int32_t *ptr = object_field_prop_ptr(obj, prop);
-
-    visit_type_int32(v, name, ptr, errp);
-}
-
-const PropertyInfo prop_info_uint32 = {
-    .name  = "uint32",
-    .get   = get_uint32,
-    .set   = set_uint32,
-    .set_default_value = field_prop_set_default_value_uint,
-};
-
-const PropertyInfo prop_info_int32 = {
-    .name  = "int32",
-    .get   = field_prop_get_int32,
-    .set   = set_int32,
-    .set_default_value = field_prop_set_default_value_int,
-};
-
-/* --- 64bit integer --- */
-
-static void get_uint64(Object *obj, Visitor *v, const char *name,
-                       void *opaque, Error **errp)
-{
-    Property *prop = opaque;
-    uint64_t *ptr = object_field_prop_ptr(obj, prop);
-
-    visit_type_uint64(v, name, ptr, errp);
-}
-
-static void set_uint64(Object *obj, Visitor *v, const char *name,
-                       void *opaque, Error **errp)
-{
-    Property *prop = opaque;
-    uint64_t *ptr = object_field_prop_ptr(obj, prop);
-
-    visit_type_uint64(v, name, ptr, errp);
-}
-
-static void get_int64(Object *obj, Visitor *v, const char *name,
-                      void *opaque, Error **errp)
-{
-    Property *prop = opaque;
-    int64_t *ptr = object_field_prop_ptr(obj, prop);
-
-    visit_type_int64(v, name, ptr, errp);
-}
-
-static void set_int64(Object *obj, Visitor *v, const char *name,
-                      void *opaque, Error **errp)
-{
-    Property *prop = opaque;
-    int64_t *ptr = object_field_prop_ptr(obj, prop);
-
-    visit_type_int64(v, name, ptr, errp);
-}
-
-const PropertyInfo prop_info_uint64 = {
-    .name  = "uint64",
-    .get   = get_uint64,
-    .set   = set_uint64,
-    .set_default_value = field_prop_set_default_value_uint,
-};
-
-const PropertyInfo prop_info_int64 = {
-    .name  = "int64",
-    .get   = get_int64,
-    .set   = set_int64,
-    .set_default_value = field_prop_set_default_value_int,
-};
-
-/* --- string --- */
-
-static void release_string(Object *obj, const char *name, void *opaque)
-{
-    Property *prop = opaque;
-    g_free(*(char **)object_field_prop_ptr(obj, prop));
-}
-
-static void get_string(Object *obj, Visitor *v, const char *name,
-                       void *opaque, Error **errp)
-{
-    Property *prop = opaque;
-    char **ptr = object_field_prop_ptr(obj, prop);
-
-    if (!*ptr) {
-        char *str = (char *)"";
-        visit_type_str(v, name, &str, errp);
-    } else {
-        visit_type_str(v, name, ptr, errp);
-    }
-}
-
-static void set_string(Object *obj, Visitor *v, const char *name,
-                       void *opaque, Error **errp)
-{
-    Property *prop = opaque;
-    char **ptr = object_field_prop_ptr(obj, prop);
-    char *str;
-
-    if (!visit_type_str(v, name, &str, errp)) {
-        return;
-    }
-    g_free(*ptr);
-    *ptr = str;
-}
-
-const PropertyInfo prop_info_string = {
-    .name  = "str",
-    .release = release_string,
-    .get   = get_string,
-    .set   = set_string,
-};
-
-/* --- on/off/auto --- */
-
-const PropertyInfo prop_info_on_off_auto = {
-    .name = "OnOffAuto",
-    .description = "on/off/auto",
-    .enum_table = &OnOffAuto_lookup,
-    .get = field_prop_get_enum,
-    .set = field_prop_set_enum,
-    .set_default_value = field_prop_set_default_value_enum,
-};
-
-/* --- 32bit unsigned int 'size' type --- */
-
-void field_prop_get_size32(Object *obj, Visitor *v, const char *name,
-                           void *opaque, Error **errp)
-{
-    Property *prop = opaque;
-    uint32_t *ptr = object_field_prop_ptr(obj, prop);
-    uint64_t value = *ptr;
-
-    visit_type_size(v, name, &value, errp);
-}
-
-static void set_size32(Object *obj, Visitor *v, const char *name, void *opaque,
-                       Error **errp)
-{
-    Property *prop = opaque;
-    uint32_t *ptr = object_field_prop_ptr(obj, prop);
-    uint64_t value;
-
-    if (!visit_type_size(v, name, &value, errp)) {
-        return;
-    }
-
-    if (value > UINT32_MAX) {
-        error_setg(errp,
-                   "Property %s.%s doesn't take value %" PRIu64
-                   " (maximum: %u)",
-                   object_get_typename(obj), name, value, UINT32_MAX);
-        return;
-    }
-
-    *ptr = value;
-}
-
-const PropertyInfo prop_info_size32 = {
-    .name  = "size",
-    .get = field_prop_get_size32,
-    .set = set_size32,
-    .set_default_value = field_prop_set_default_value_uint,
-};
-
-/* --- support for array properties --- */
-
-static void set_prop_arraylen(Object *obj, Visitor *v, const char *name,
-                              void *opaque, Error **errp)
-{
-    /* Setter for the property which defines the length of a
-     * variable-sized property array. As well as actually setting the
-     * array-length field in the device struct, we have to create the
-     * array itself and dynamically add the corresponding properties.
-     */
-    Property *prop = opaque;
-    ObjectProperty *op = object_property_find_err(obj, name, &error_abort);
-    uint32_t *alenptr = object_field_prop_ptr(obj, prop);
-    void **arrayptr = (void *)obj + prop->arrayoffset;
-    void *eltptr;
-    const char *arrayname;
-    int i;
-
-    if (*alenptr) {
-        error_setg(errp, "array size property %s may not be set more than once",
-                   name);
-        return;
-    }
-    if (!visit_type_uint32(v, name, alenptr, errp)) {
-        return;
-    }
-    if (!*alenptr) {
-        return;
-    }
-
-    /* DEFINE_PROP_ARRAY guarantees that name should start with this prefix;
-     * strip it off so we can get the name of the array itself.
-     */
-    assert(strncmp(name, PROP_ARRAY_LEN_PREFIX,
-                   strlen(PROP_ARRAY_LEN_PREFIX)) == 0);
-    arrayname = name + strlen(PROP_ARRAY_LEN_PREFIX);
-
-    /* Note that it is the responsibility of the individual device's deinit
-     * to free the array proper.
-     */
-    *arrayptr = eltptr = g_malloc0(*alenptr * prop->arrayfieldsize);
-    for (i = 0; i < *alenptr; i++, eltptr += prop->arrayfieldsize) {
-        g_autofree char *propname = g_strdup_printf("%s[%d]", arrayname, i);
-        Property *arrayprop = g_new0(Property, 1);
-        arrayprop->info = prop->arrayinfo;
-        /* This ugly piece of pointer arithmetic sets up the offset so
-         * that when the underlying get/set hooks call qdev_get_prop_ptr
-         * they get the right answer despite the array element not actually
-         * being inside the device struct.
-         */
-        arrayprop->offset = eltptr - (void *)obj;
-        assert(object_field_prop_ptr(obj, arrayprop) == eltptr);
-        object_property_add_field(obj, propname, arrayprop, op->allow_set);
-    }
-}
-
-const PropertyInfo prop_info_arraylen = {
-    .name = "uint32",
-    .get = get_uint32,
-    .set = set_prop_arraylen,
-    .set_default_value = field_prop_set_default_value_uint,
-};
-
 /* --- public helpers --- */
 
 static Property *qdev_prop_walk(Property *props, const char *name)
@@ -712,53 +222,6 @@  void qdev_prop_set_globals(DeviceState *dev)
                               dev->hotplugged ? NULL : &error_fatal);
 }
 
-/* --- 64bit unsigned int 'size' type --- */
-
-static void get_size(Object *obj, Visitor *v, const char *name, void *opaque,
-                     Error **errp)
-{
-    Property *prop = opaque;
-    uint64_t *ptr = object_field_prop_ptr(obj, prop);
-
-    visit_type_size(v, name, ptr, errp);
-}
-
-static void set_size(Object *obj, Visitor *v, const char *name, void *opaque,
-                     Error **errp)
-{
-    Property *prop = opaque;
-    uint64_t *ptr = object_field_prop_ptr(obj, prop);
-
-    visit_type_size(v, name, ptr, errp);
-}
-
-const PropertyInfo prop_info_size = {
-    .name  = "size",
-    .get = get_size,
-    .set = set_size,
-    .set_default_value = field_prop_set_default_value_uint,
-};
-
-/* --- object link property --- */
-
-static ObjectProperty *create_link_property(ObjectClass *oc, const char *name,
-                                            Property *prop)
-{
-    /*
-     * NOTE: object_property_allow_set_link is unconditional, but
-     *       ObjectProperty.allow_set may be set for the property too.
-     */
-    return object_class_property_add_link(oc, name, prop->link_type,
-                                          prop->offset,
-                                          object_property_allow_set_link,
-                                          OBJ_PROP_LINK_STRONG);
-}
-
-const PropertyInfo prop_info_link = {
-    .name = "link",
-    .create = create_link_property,
-};
-
 void qdev_property_add_static(DeviceState *dev, Property *prop)
 {
     object_property_add_field(OBJECT(dev), prop->qdev_prop_name, prop,
diff --git a/qom/property-types.c b/qom/property-types.c
new file mode 100644
index 0000000000..f566c05ec2
--- /dev/null
+++ b/qom/property-types.c
@@ -0,0 +1,545 @@ 
+#include "qemu/osdep.h"
+#include "qom/field-property.h"
+#include "qom/property-types.h"
+#include "qom/field-property-internal.h"
+#include "qapi/qapi-types-common.h"
+#include "qapi/visitor.h"
+#include "qapi/error.h"
+#include "qemu/uuid.h"
+
+void field_prop_get_enum(Object *obj, Visitor *v, const char *name,
+                         void *opaque, Error **errp)
+{
+    Property *prop = opaque;
+    int *ptr = object_field_prop_ptr(obj, prop);
+
+    visit_type_enum(v, name, ptr, prop->info->enum_table, errp);
+}
+
+void field_prop_set_enum(Object *obj, Visitor *v, const char *name,
+                         void *opaque, Error **errp)
+{
+    Property *prop = opaque;
+    int *ptr = object_field_prop_ptr(obj, prop);
+
+    visit_type_enum(v, name, ptr, prop->info->enum_table, errp);
+}
+
+void field_prop_set_default_value_enum(ObjectProperty *op,
+                                       const Property *prop)
+{
+    object_property_set_default_str(op,
+        qapi_enum_lookup(prop->info->enum_table, prop->defval.i));
+}
+
+const PropertyInfo prop_info_enum = {
+    .name  = "enum",
+    .get   = field_prop_get_enum,
+    .set   = field_prop_set_enum,
+    .set_default_value = field_prop_set_default_value_enum,
+};
+
+/* Bit */
+
+static uint32_t qdev_get_prop_mask(Property *prop)
+{
+    assert(prop->info == &prop_info_bit);
+    return 0x1 << prop->bitnr;
+}
+
+static void bit_prop_set(Object *obj, Property *props, bool val)
+{
+    uint32_t *p = object_field_prop_ptr(obj, props);
+    uint32_t mask = qdev_get_prop_mask(props);
+    if (val) {
+        *p |= mask;
+    } else {
+        *p &= ~mask;
+    }
+}
+
+static void prop_get_bit(Object *obj, Visitor *v, const char *name,
+                         void *opaque, Error **errp)
+{
+    Property *prop = opaque;
+    uint32_t *p = object_field_prop_ptr(obj, prop);
+    bool value = (*p & qdev_get_prop_mask(prop)) != 0;
+
+    visit_type_bool(v, name, &value, errp);
+}
+
+static void prop_set_bit(Object *obj, Visitor *v, const char *name,
+                         void *opaque, Error **errp)
+{
+    Property *prop = opaque;
+    bool value;
+
+    if (!visit_type_bool(v, name, &value, errp)) {
+        return;
+    }
+    bit_prop_set(obj, prop, value);
+}
+
+static void set_default_value_bool(ObjectProperty *op, const Property *prop)
+{
+    object_property_set_default_bool(op, prop->defval.u);
+}
+
+const PropertyInfo prop_info_bit = {
+    .name  = "bool",
+    .description = "on/off",
+    .get   = prop_get_bit,
+    .set   = prop_set_bit,
+    .set_default_value = set_default_value_bool,
+};
+
+/* Bit64 */
+
+static uint64_t qdev_get_prop_mask64(Property *prop)
+{
+    assert(prop->info == &prop_info_bit64);
+    return 0x1ull << prop->bitnr;
+}
+
+static void bit64_prop_set(Object *obj, Property *props, bool val)
+{
+    uint64_t *p = object_field_prop_ptr(obj, props);
+    uint64_t mask = qdev_get_prop_mask64(props);
+    if (val) {
+        *p |= mask;
+    } else {
+        *p &= ~mask;
+    }
+}
+
+static void prop_get_bit64(Object *obj, Visitor *v, const char *name,
+                           void *opaque, Error **errp)
+{
+    Property *prop = opaque;
+    uint64_t *p = object_field_prop_ptr(obj, prop);
+    bool value = (*p & qdev_get_prop_mask64(prop)) != 0;
+
+    visit_type_bool(v, name, &value, errp);
+}
+
+static void prop_set_bit64(Object *obj, Visitor *v, const char *name,
+                           void *opaque, Error **errp)
+{
+    Property *prop = opaque;
+    bool value;
+
+    if (!visit_type_bool(v, name, &value, errp)) {
+        return;
+    }
+    bit64_prop_set(obj, prop, value);
+}
+
+const PropertyInfo prop_info_bit64 = {
+    .name  = "bool",
+    .description = "on/off",
+    .get   = prop_get_bit64,
+    .set   = prop_set_bit64,
+    .set_default_value = set_default_value_bool,
+};
+
+/* --- bool --- */
+
+static void get_bool(Object *obj, Visitor *v, const char *name, void *opaque,
+                     Error **errp)
+{
+    Property *prop = opaque;
+    bool *ptr = object_field_prop_ptr(obj, prop);
+
+    visit_type_bool(v, name, ptr, errp);
+}
+
+static void set_bool(Object *obj, Visitor *v, const char *name, void *opaque,
+                     Error **errp)
+{
+    Property *prop = opaque;
+    bool *ptr = object_field_prop_ptr(obj, prop);
+
+    visit_type_bool(v, name, ptr, errp);
+}
+
+const PropertyInfo prop_info_bool = {
+    .name  = "bool",
+    .get   = get_bool,
+    .set   = set_bool,
+    .set_default_value = set_default_value_bool,
+};
+
+/* --- 8bit integer --- */
+
+static void get_uint8(Object *obj, Visitor *v, const char *name, void *opaque,
+                      Error **errp)
+{
+    Property *prop = opaque;
+    uint8_t *ptr = object_field_prop_ptr(obj, prop);
+
+    visit_type_uint8(v, name, ptr, errp);
+}
+
+static void set_uint8(Object *obj, Visitor *v, const char *name, void *opaque,
+                      Error **errp)
+{
+    Property *prop = opaque;
+    uint8_t *ptr = object_field_prop_ptr(obj, prop);
+
+    visit_type_uint8(v, name, ptr, errp);
+}
+
+void field_prop_set_default_value_int(ObjectProperty *op,
+                                      const Property *prop)
+{
+    object_property_set_default_int(op, prop->defval.i);
+}
+
+void field_prop_set_default_value_uint(ObjectProperty *op,
+                                       const Property *prop)
+{
+    object_property_set_default_uint(op, prop->defval.u);
+}
+
+const PropertyInfo prop_info_uint8 = {
+    .name  = "uint8",
+    .get   = get_uint8,
+    .set   = set_uint8,
+    .set_default_value = field_prop_set_default_value_uint,
+};
+
+/* --- 16bit integer --- */
+
+static void get_uint16(Object *obj, Visitor *v, const char *name,
+                       void *opaque, Error **errp)
+{
+    Property *prop = opaque;
+    uint16_t *ptr = object_field_prop_ptr(obj, prop);
+
+    visit_type_uint16(v, name, ptr, errp);
+}
+
+static void set_uint16(Object *obj, Visitor *v, const char *name,
+                       void *opaque, Error **errp)
+{
+    Property *prop = opaque;
+    uint16_t *ptr = object_field_prop_ptr(obj, prop);
+
+    visit_type_uint16(v, name, ptr, errp);
+}
+
+const PropertyInfo prop_info_uint16 = {
+    .name  = "uint16",
+    .get   = get_uint16,
+    .set   = set_uint16,
+    .set_default_value = field_prop_set_default_value_uint,
+};
+
+/* --- 32bit integer --- */
+
+static void get_uint32(Object *obj, Visitor *v, const char *name,
+                       void *opaque, Error **errp)
+{
+    Property *prop = opaque;
+    uint32_t *ptr = object_field_prop_ptr(obj, prop);
+
+    visit_type_uint32(v, name, ptr, errp);
+}
+
+static void set_uint32(Object *obj, Visitor *v, const char *name,
+                       void *opaque, Error **errp)
+{
+    Property *prop = opaque;
+    uint32_t *ptr = object_field_prop_ptr(obj, prop);
+
+    visit_type_uint32(v, name, ptr, errp);
+}
+
+void field_prop_get_int32(Object *obj, Visitor *v, const char *name,
+                          void *opaque, Error **errp)
+{
+    Property *prop = opaque;
+    int32_t *ptr = object_field_prop_ptr(obj, prop);
+
+    visit_type_int32(v, name, ptr, errp);
+}
+
+static void set_int32(Object *obj, Visitor *v, const char *name, void *opaque,
+                      Error **errp)
+{
+    Property *prop = opaque;
+    int32_t *ptr = object_field_prop_ptr(obj, prop);
+
+    visit_type_int32(v, name, ptr, errp);
+}
+
+const PropertyInfo prop_info_uint32 = {
+    .name  = "uint32",
+    .get   = get_uint32,
+    .set   = set_uint32,
+    .set_default_value = field_prop_set_default_value_uint,
+};
+
+const PropertyInfo prop_info_int32 = {
+    .name  = "int32",
+    .get   = field_prop_get_int32,
+    .set   = set_int32,
+    .set_default_value = field_prop_set_default_value_int,
+};
+
+/* --- 64bit integer --- */
+
+static void get_uint64(Object *obj, Visitor *v, const char *name,
+                       void *opaque, Error **errp)
+{
+    Property *prop = opaque;
+    uint64_t *ptr = object_field_prop_ptr(obj, prop);
+
+    visit_type_uint64(v, name, ptr, errp);
+}
+
+static void set_uint64(Object *obj, Visitor *v, const char *name,
+                       void *opaque, Error **errp)
+{
+    Property *prop = opaque;
+    uint64_t *ptr = object_field_prop_ptr(obj, prop);
+
+    visit_type_uint64(v, name, ptr, errp);
+}
+
+static void get_int64(Object *obj, Visitor *v, const char *name,
+                      void *opaque, Error **errp)
+{
+    Property *prop = opaque;
+    int64_t *ptr = object_field_prop_ptr(obj, prop);
+
+    visit_type_int64(v, name, ptr, errp);
+}
+
+static void set_int64(Object *obj, Visitor *v, const char *name,
+                      void *opaque, Error **errp)
+{
+    Property *prop = opaque;
+    int64_t *ptr = object_field_prop_ptr(obj, prop);
+
+    visit_type_int64(v, name, ptr, errp);
+}
+
+const PropertyInfo prop_info_uint64 = {
+    .name  = "uint64",
+    .get   = get_uint64,
+    .set   = set_uint64,
+    .set_default_value = field_prop_set_default_value_uint,
+};
+
+const PropertyInfo prop_info_int64 = {
+    .name  = "int64",
+    .get   = get_int64,
+    .set   = set_int64,
+    .set_default_value = field_prop_set_default_value_int,
+};
+
+/* --- string --- */
+
+static void release_string(Object *obj, const char *name, void *opaque)
+{
+    Property *prop = opaque;
+    g_free(*(char **)object_field_prop_ptr(obj, prop));
+}
+
+static void get_string(Object *obj, Visitor *v, const char *name,
+                       void *opaque, Error **errp)
+{
+    Property *prop = opaque;
+    char **ptr = object_field_prop_ptr(obj, prop);
+
+    if (!*ptr) {
+        char *str = (char *)"";
+        visit_type_str(v, name, &str, errp);
+    } else {
+        visit_type_str(v, name, ptr, errp);
+    }
+}
+
+static void set_string(Object *obj, Visitor *v, const char *name,
+                       void *opaque, Error **errp)
+{
+    Property *prop = opaque;
+    char **ptr = object_field_prop_ptr(obj, prop);
+    char *str;
+
+    if (!visit_type_str(v, name, &str, errp)) {
+        return;
+    }
+    g_free(*ptr);
+    *ptr = str;
+}
+
+const PropertyInfo prop_info_string = {
+    .name  = "str",
+    .release = release_string,
+    .get   = get_string,
+    .set   = set_string,
+};
+
+/* --- on/off/auto --- */
+
+const PropertyInfo prop_info_on_off_auto = {
+    .name = "OnOffAuto",
+    .description = "on/off/auto",
+    .enum_table = &OnOffAuto_lookup,
+    .get = field_prop_get_enum,
+    .set = field_prop_set_enum,
+    .set_default_value = field_prop_set_default_value_enum,
+};
+
+/* --- 32bit unsigned int 'size' type --- */
+
+void field_prop_get_size32(Object *obj, Visitor *v, const char *name,
+                           void *opaque, Error **errp)
+{
+    Property *prop = opaque;
+    uint32_t *ptr = object_field_prop_ptr(obj, prop);
+    uint64_t value = *ptr;
+
+    visit_type_size(v, name, &value, errp);
+}
+
+static void set_size32(Object *obj, Visitor *v, const char *name, void *opaque,
+                       Error **errp)
+{
+    Property *prop = opaque;
+    uint32_t *ptr = object_field_prop_ptr(obj, prop);
+    uint64_t value;
+
+    if (!visit_type_size(v, name, &value, errp)) {
+        return;
+    }
+
+    if (value > UINT32_MAX) {
+        error_setg(errp,
+                   "Property %s.%s doesn't take value %" PRIu64
+                   " (maximum: %u)",
+                   object_get_typename(obj), name, value, UINT32_MAX);
+        return;
+    }
+
+    *ptr = value;
+}
+
+const PropertyInfo prop_info_size32 = {
+    .name  = "size",
+    .get = field_prop_get_size32,
+    .set = set_size32,
+    .set_default_value = field_prop_set_default_value_uint,
+};
+
+/* --- support for array properties --- */
+
+static void set_prop_arraylen(Object *obj, Visitor *v, const char *name,
+                              void *opaque, Error **errp)
+{
+    /* Setter for the property which defines the length of a
+     * variable-sized property array. As well as actually setting the
+     * array-length field in the device struct, we have to create the
+     * array itself and dynamically add the corresponding properties.
+     */
+    Property *prop = opaque;
+    ObjectProperty *op = object_property_find_err(obj, name, &error_abort);
+    uint32_t *alenptr = object_field_prop_ptr(obj, prop);
+    void **arrayptr = (void *)obj + prop->arrayoffset;
+    void *eltptr;
+    const char *arrayname;
+    int i;
+
+    if (*alenptr) {
+        error_setg(errp, "array size property %s may not be set more than once",
+                   name);
+        return;
+    }
+    if (!visit_type_uint32(v, name, alenptr, errp)) {
+        return;
+    }
+    if (!*alenptr) {
+        return;
+    }
+
+    /* DEFINE_PROP_ARRAY guarantees that name should start with this prefix;
+     * strip it off so we can get the name of the array itself.
+     */
+    assert(strncmp(name, PROP_ARRAY_LEN_PREFIX,
+                   strlen(PROP_ARRAY_LEN_PREFIX)) == 0);
+    arrayname = name + strlen(PROP_ARRAY_LEN_PREFIX);
+
+    /* Note that it is the responsibility of the individual device's deinit
+     * to free the array proper.
+     */
+    *arrayptr = eltptr = g_malloc0(*alenptr * prop->arrayfieldsize);
+    for (i = 0; i < *alenptr; i++, eltptr += prop->arrayfieldsize) {
+        g_autofree char *propname = g_strdup_printf("%s[%d]", arrayname, i);
+        Property *arrayprop = g_new0(Property, 1);
+        arrayprop->info = prop->arrayinfo;
+        /* This ugly piece of pointer arithmetic sets up the offset so
+         * that when the underlying get/set hooks call qdev_get_prop_ptr
+         * they get the right answer despite the array element not actually
+         * being inside the device struct.
+         */
+        arrayprop->offset = eltptr - (void *)obj;
+        assert(object_field_prop_ptr(obj, arrayprop) == eltptr);
+        object_property_add_field(obj, propname, arrayprop, op->allow_set);
+    }
+}
+
+const PropertyInfo prop_info_arraylen = {
+    .name = "uint32",
+    .get = get_uint32,
+    .set = set_prop_arraylen,
+    .set_default_value = field_prop_set_default_value_uint,
+};
+
+/* --- 64bit unsigned int 'size' type --- */
+
+static void get_size(Object *obj, Visitor *v, const char *name, void *opaque,
+                     Error **errp)
+{
+    Property *prop = opaque;
+    uint64_t *ptr = object_field_prop_ptr(obj, prop);
+
+    visit_type_size(v, name, ptr, errp);
+}
+
+static void set_size(Object *obj, Visitor *v, const char *name, void *opaque,
+                     Error **errp)
+{
+    Property *prop = opaque;
+    uint64_t *ptr = object_field_prop_ptr(obj, prop);
+
+    visit_type_size(v, name, ptr, errp);
+}
+
+const PropertyInfo prop_info_size = {
+    .name  = "size",
+    .get = get_size,
+    .set = set_size,
+    .set_default_value = field_prop_set_default_value_uint,
+};
+
+/* --- object link property --- */
+
+static ObjectProperty *create_link_property(ObjectClass *oc, const char *name,
+                                            Property *prop)
+{
+    /*
+     * NOTE: object_property_allow_set_link is unconditional, but
+     *       ObjectProperty.allow_set may be set for the property too.
+     */
+    return object_class_property_add_link(oc, name, prop->link_type,
+                                          prop->offset,
+                                          object_property_allow_set_link,
+                                          OBJ_PROP_LINK_STRONG);
+}
+
+const PropertyInfo prop_info_link = {
+    .name = "link",
+    .create = create_link_property,
+};
diff --git a/qom/meson.build b/qom/meson.build
index e83794454d..7fdfd6fe7b 100644
--- a/qom/meson.build
+++ b/qom/meson.build
@@ -5,6 +5,7 @@  qom_ss.add(files(
   'object_interfaces.c',
   'qom-qobject.c',
   'field-property.c',
+  'property-types.c',
 ))
 
 qmp_ss.add(files('qom-qmp-cmds.c'))