Messages in this thread | | | Date | Sun, 11 Jun 2023 15:47:08 +0000 | From | Benno Lossin <> | Subject | Re: [PATCH v2 2/8] rust: add offset_of! macro |
| |
On 01.06.23 15:49, Alice Ryhl wrote: > From: Wedson Almeida Filho <walmeida@microsoft.com> > > This macro is used to compute the offset of a field in a struct. > > This commit enables an unstable feature that is necessary for using > the macro in a constant. However, this is not a problem as the macro > will become available from the Rust standard library soon [1]. The > unstable feature can be disabled again once that happens. > > The macro in this patch does not support sub-fields. That is, you cannot > write `offset_of!(MyStruct, field.sub_field)` to get the offset of > `sub_field` with `field`'s type being a struct with a field called > `sub_field`. This is because `field` might be a `Box<SubStruct>`, which > means that you would be trying to compute the offset to something in an > entirely different allocation. There's no easy way to fix the current > macro to support subfields, but the version being added to the standard > library should support it, so the limitation is temporary and not a big > deal. > > Link: https://github.com/rust-lang/rust/issues/106655 [1] > Signed-off-by: Wedson Almeida Filho <walmeida@microsoft.com> > Co-developed-by: Alice Ryhl <aliceryhl@google.com> > Signed-off-by: Alice Ryhl <aliceryhl@google.com> > Reviewed-by: Martin Rodriguez Reboredo <yakoyoku@gmail.com>
Reviewed-by: Benno Lossin <benno.lossin@proton.me>
-- Cheers, Benno
> --- > rust/kernel/lib.rs | 35 +++++++++++++++++++++++++++++++++++ > scripts/Makefile.build | 2 +- > 2 files changed, 36 insertions(+), 1 deletion(-) > > diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs > index eaded02ffb01..7ea777b731e6 100644 > --- a/rust/kernel/lib.rs > +++ b/rust/kernel/lib.rs > @@ -14,6 +14,7 @@ > #![no_std] > #![feature(allocator_api)] > #![feature(coerce_unsized)] > +#![feature(const_refs_to_cell)] > #![feature(dispatch_from_dyn)] > #![feature(new_uninit)] > #![feature(receiver_trait)] > @@ -98,3 +99,37 @@ fn panic(info: &core::panic::PanicInfo<'_>) -> ! { > // instead of `!`. See <https://github.com/rust-lang/rust-bindgen/issues/2094>. > loop {} > } > + > +/// Calculates the offset of a field from the beginning of the struct it belongs to. > +/// > +/// # Examples > +/// > +/// ``` > +/// #[repr(C)] > +/// struct Test { > +/// a: u64, > +/// b: u32, > +/// } > +/// > +/// assert_eq!(kernel::offset_of!(Test, b), 8); > +/// ``` > +#[macro_export] > +macro_rules! offset_of { > + ($type:path, $field:ident) => {{ > + let $type { $field: _, .. }; > + let tmp = ::core::mem::MaybeUninit::<$type>::uninit(); > + let outer = tmp.as_ptr(); > + // To avoid warnings when nesting `unsafe` blocks. > + #[allow(unused_unsafe)] > + // SAFETY: The pointer is valid and aligned, just not initialised; `addr_of` ensures that > + // we don't actually read from `outer` (which would be UB) nor create an intermediate > + // reference. > + let inner = unsafe { ::core::ptr::addr_of!((*outer).$field) } as *const u8; > + // To avoid warnings when nesting `unsafe` blocks. > + #[allow(unused_unsafe)] > + // SAFETY: The two pointers are within the same allocation block. > + unsafe { > + inner.offset_from(outer as *const u8) as usize > + } > + }}; > +} > diff --git a/scripts/Makefile.build b/scripts/Makefile.build > index 78175231c969..819510694769 100644 > --- a/scripts/Makefile.build > +++ b/scripts/Makefile.build > @@ -277,7 +277,7 @@ $(obj)/%.lst: $(src)/%.c FORCE > # Compile Rust sources (.rs) > # --------------------------------------------------------------------------- > > -rust_allowed_features := new_uninit > +rust_allowed_features := const_refs_to_cell,new_uninit > > rust_common_cmd = \ > RUST_MODFILE=$(modfile) $(RUSTC_OR_CLIPPY) $(rust_flags) \ > -- > 2.41.0.rc0.172.g3f132b7071-goog >
| |