* [RFC 1/2] rust/qemu-api: Fix fragment-specifiers in define_property macro
2024-10-17 14:32 [RFC 0/2] rust/qemu-api: Rethink property definition macro Zhao Liu
@ 2024-10-17 14:32 ` Zhao Liu
2024-10-17 14:32 ` [RFC 2/2] rust/qemu-api: Bind PropertyInfo to type Zhao Liu
1 sibling, 0 replies; 3+ messages in thread
From: Zhao Liu @ 2024-10-17 14:32 UTC (permalink / raw)
To: Manos Pitsidianakis, Paolo Bonzini, Alex Bennée,
Daniel P . Berrangé
Cc: qemu-devel, Junjie Mao, Zhao Liu
From: Junjie Mao <junjie.mao@hotmail.com>
For the matcher of macro, "expr" is used for expressions, while "ident"
is used for variable/function names, and "ty" matches types.
In define_property macro, $field is a member name of type $state, so it
should be defined as "ident", though offset_of! doesn't complain about
this. $type is the type of $field, since it is not used in the macro, so
that no type mismatch error is triggered either.
Fix fragment-specifiers of $field and $type.
Signed-off-by: Junjie Mao <junjie.mao@hotmail.com>
Co-developed-by: Zhao Liu <zhao1.liu@intel.com>
Signed-off-by: Zhao Liu <zhao1.liu@intel.com>
---
rust/qemu-api/src/device_class.rs | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/rust/qemu-api/src/device_class.rs b/rust/qemu-api/src/device_class.rs
index 1ea95beb78db..be363fd63223 100644
--- a/rust/qemu-api/src/device_class.rs
+++ b/rust/qemu-api/src/device_class.rs
@@ -26,7 +26,7 @@ macro_rules! device_class_init {
#[macro_export]
macro_rules! define_property {
- ($name:expr, $state:ty, $field:expr, $prop:expr, $type:expr, default = $defval:expr$(,)*) => {
+ ($name:expr, $state:ty, $field:ident, $prop:expr, $type:ty, default = $defval:expr$(,)*) => {
$crate::bindings::Property {
name: {
#[used]
@@ -47,7 +47,7 @@ macro_rules! define_property {
link_type: ::core::ptr::null(),
}
};
- ($name:expr, $state:ty, $field:expr, $prop:expr, $type:expr$(,)*) => {
+ ($name:expr, $state:ty, $field:ident, $prop:expr, $type:ty$(,)*) => {
$crate::bindings::Property {
name: {
#[used]
--
2.34.1
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [RFC 2/2] rust/qemu-api: Bind PropertyInfo to type
2024-10-17 14:32 [RFC 0/2] rust/qemu-api: Rethink property definition macro Zhao Liu
2024-10-17 14:32 ` [RFC 1/2] rust/qemu-api: Fix fragment-specifiers in define_property macro Zhao Liu
@ 2024-10-17 14:32 ` Zhao Liu
1 sibling, 0 replies; 3+ messages in thread
From: Zhao Liu @ 2024-10-17 14:32 UTC (permalink / raw)
To: Manos Pitsidianakis, Paolo Bonzini, Alex Bennée,
Daniel P . Berrangé
Cc: qemu-devel, Junjie Mao, Zhao Liu
For traditional property definitions implemented in C, since the C
language cannot bind variable types to specific methods or variables,
user must specify the concrete PropertyInfo and variable type in the
DEFINE_PROP macro and its variants. Then the property macro effectively
associate PropertyInfo with variable type through clever check.
However, in Rust, this process can be more elegant. By introducing the
PropertyType trait, QAPI (in Rust) can associate PropertyInfo with
specific types, allowing Rust to infer the predefined PropertyInfo from
the variable type.
This avoids user errors in passing incorrect PropertyInfo and simplifies
property definitions. And based on this enhancement, the property
definition macro can eliminate the need for the type and prop parameters.
Co-developed-by: Junjie Mao <junjie.mao@hotmail.com>
Signed-off-by: Junjie Mao <junjie.mao@hotmail.com>
Signed-off-by: Zhao Liu <zhao1.liu@intel.com>
---
rust/hw/char/pl011/src/device_class.rs | 4 ---
rust/qemu-api/src/device_class.rs | 48 +++++++++++++++++++++++---
rust/qemu-api/src/tests.rs | 4 ---
3 files changed, 43 insertions(+), 13 deletions(-)
diff --git a/rust/hw/char/pl011/src/device_class.rs b/rust/hw/char/pl011/src/device_class.rs
index b7ab31af02d7..295e970e8564 100644
--- a/rust/hw/char/pl011/src/device_class.rs
+++ b/rust/hw/char/pl011/src/device_class.rs
@@ -21,15 +21,11 @@
c"chardev",
PL011State,
char_backend,
- unsafe { &qdev_prop_chr },
- CharBackend
),
qemu_api::define_property!(
c"migrate-clk",
PL011State,
migrate_clock,
- unsafe { &qdev_prop_bool },
- bool
),
}
diff --git a/rust/qemu-api/src/device_class.rs b/rust/qemu-api/src/device_class.rs
index be363fd63223..0b9d6ca705d3 100644
--- a/rust/qemu-api/src/device_class.rs
+++ b/rust/qemu-api/src/device_class.rs
@@ -4,7 +4,7 @@
use std::sync::OnceLock;
-use crate::bindings::Property;
+use crate::bindings::{CharBackend, Property, PropertyInfo, qdev_prop_chr, qdev_prop_bool};
#[macro_export]
macro_rules! device_class_init {
@@ -24,16 +24,54 @@ macro_rules! device_class_init {
};
}
+pub trait PropertyType {
+ fn get_prop_info() -> *const PropertyInfo;
+}
+
+pub trait PropertyTypeImpl<T: PropertyType> {
+ fn get_prop_info(_: *const T) -> *const PropertyInfo;
+}
+
+impl<T: PropertyType> PropertyTypeImpl<T> for () {
+ fn get_prop_info(_: *const T) -> *const PropertyInfo {
+ T::get_prop_info()
+ }
+}
+
+impl PropertyType for CharBackend {
+ fn get_prop_info() -> *const PropertyInfo {
+ // SAFETY: Access to a defined c-structure, no other operation is performed.
+ unsafe { std::ptr::addr_of!(qdev_prop_chr) }
+ }
+}
+
+impl PropertyType for bool {
+ fn get_prop_info() -> *const PropertyInfo {
+ // SAFETY: Access to a defined c-structure, no other operation is performed.
+ unsafe { std::ptr::addr_of!(qdev_prop_bool) }
+ }
+}
+
+#[macro_export]
+macro_rules! get_prop_info {
+ ($state:ty, $field:ident) => {{
+ use $crate::device_class::PropertyTypeImpl;
+ let base = std::mem::MaybeUninit::<$state>::uninit().as_ptr();
+ <()>::get_prop_info(unsafe { std::ptr::addr_of!((*base).$field) })
+ }};
+}
+
+
#[macro_export]
macro_rules! define_property {
- ($name:expr, $state:ty, $field:ident, $prop:expr, $type:ty, default = $defval:expr$(,)*) => {
+ ($name:expr, $state:ty, $field:ident, default = $defval:expr$(,)*) => {
$crate::bindings::Property {
name: {
#[used]
static _TEMP: &::core::ffi::CStr = $name;
_TEMP.as_ptr()
},
- info: $prop,
+ info: $crate::get_prop_info!($state, $field),
offset: ::core::mem::offset_of!($state, $field)
.try_into()
.expect("Could not fit offset value to type"),
@@ -47,14 +85,14 @@ macro_rules! define_property {
link_type: ::core::ptr::null(),
}
};
- ($name:expr, $state:ty, $field:ident, $prop:expr, $type:ty$(,)*) => {
+ ($name:expr, $state:ty, $field:ident$(,)*) => {
$crate::bindings::Property {
name: {
#[used]
static _TEMP: &::core::ffi::CStr = $name;
_TEMP.as_ptr()
},
- info: $prop,
+ info: $crate::get_prop_info!($state, $field),
offset: ::core::mem::offset_of!($state, $field)
.try_into()
.expect("Could not fit offset value to type"),
diff --git a/rust/qemu-api/src/tests.rs b/rust/qemu-api/src/tests.rs
index df54edbd4e27..d2b7451ef707 100644
--- a/rust/qemu-api/src/tests.rs
+++ b/rust/qemu-api/src/tests.rs
@@ -27,15 +27,11 @@ pub struct DummyState {
c"chardev",
DummyState,
char_backend,
- unsafe { &qdev_prop_chr },
- CharBackend
),
define_property!(
c"migrate-clk",
DummyState,
migrate_clock,
- unsafe { &qdev_prop_bool },
- bool
),
}
--
2.34.1
^ permalink raw reply related [flat|nested] 3+ messages in thread