diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2026-08-24 08:46:03 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2026-08-24 08:46:03 -0700 |
| commit | cf9610f9116d55c5a66ef9f1faecacabd93a9322 (patch) | |
| tree | 757a3d280760c654767631cab5ad8af2d86d1848 /rust/zerocopy-derive/derive/mod.rs | |
| download | linux-stable-cf9610f9116d55c5a66ef9f1faecacabd93a9322.tar.gz linux-stable-cf9610f9116d55c5a66ef9f1faecacabd93a9322.zip | |
Merge tag 'pinctrl-v7.3-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrlgrafted
Pull pin control updates from Linus Walleij:
"Core changes:
- Use the non-blocking mux_state_try_select() in the generic MUX pin
control back-end
- Free pin maps on pinctrl_generic_to_map() failure in the core
helpers
New hardware pin control:
- Qualcomm Maili TLMM SoC, PMG1110 PMIC, and Eliza LPASS LPI TLMM SoC
(this is for the low power audio, LPASS = Low Power Audio SubSystem
portions)
- Upboard support on top of the Intel pin controller
- Apple T6030 and T6031 support (just compatible strings)
- Samsung Exynos 8855 SoC
- Mediatek MT6858 SoC
- Rockchip RK3308B and RV1106 SoCs
- Airoha EN7523 and AN7563 SoCs
Improvements:
- Qualcomm TLMM GPIOs are unconditionally marked as wakeup capable
- Qualcomm improvements on top of the Qualcomm PDC (power domain
controller) irqchip improvements from tglx:s tree
- Qualcomm IPQ806x and IPQ9650 non-urgent pin grop fixups
- The NPCM8xx driver has been put into shape fixing many pin and
group definitions
- Some non-urgent Tegra 264 pin assignments are fixed up
- Some non-urgent fixups to Airoha AN7581 and AN7583 registers and
pin assignments, missing features etc"
* tag 'pinctrl-v7.3-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl: (130 commits)
dt-bindings: pinctrl: Convert TI DA850 pupd to DT schema
pinctrl: meson: sync some modify from A4
pinctrl: meson: a4: Add input enable pin configuration
pinctrl: realtek: rtd1625: remove unused group name spdif_sel
pinctrl: realtek: rtd1625: fix base_bit for VE4 GPIO 13
dt-bindings: pinctrl: microchip,pic32mzda-pinctrl: Convert to DT schema
Revert "Merge branch 'ib-rsk7204' into devel"
pinctrl: rockchip: Add RV1106 pinctrl support
dt-bindings: pinctrl: rockchip: Add RV1106 compatible
pinctrl: rockchip: Decode drive strength in the get function
pinctrl: fix PINCTRL_GENERIC_MUX not always being selectable
pinctrl: airoha: add support of an7563 SoC
dt-bindings: pinctrl: airoha: add support of an7563 pin controller
pinctrl: airoha: try to find chip scu node by phandle first
pinctrl: airoha: add support of en7523 SoC
dt-bindings: pinctrl: airoha: add support of en7523 pin controller
pinctrl: airoha: an7583: add support for olt pinmux
pinctrl: airoha: an7583: add support for pon_alt pinmux
pinctrl: airoha: an7583: add support for npu_uart pinmux
dt-bindings: pinctrl: airoha: an7583: add missed features
...
Diffstat (limited to 'rust/zerocopy-derive/derive/mod.rs')
| -rw-r--r-- | rust/zerocopy-derive/derive/mod.rs | 136 |
1 files changed, 136 insertions, 0 deletions
diff --git a/rust/zerocopy-derive/derive/mod.rs b/rust/zerocopy-derive/derive/mod.rs new file mode 100644 index 000000000..b3839fcf7 --- /dev/null +++ b/rust/zerocopy-derive/derive/mod.rs @@ -0,0 +1,136 @@ +// SPDX-License-Identifier: (BSD-2-Clause OR Apache-2.0) OR MIT +// +pub mod from_bytes; +pub mod into_bytes; +pub mod known_layout; +pub mod try_from_bytes; +pub mod unaligned; + +use proc_macro2::{Span, TokenStream}; +use quote::quote; +use syn::{Data, Error}; + +use crate::{ + repr::StructUnionRepr, + util::{Ctx, DataExt, FieldBounds, ImplBlockBuilder, Trait}, +}; + +pub(crate) fn derive_immutable(ctx: &Ctx, _top_level: Trait) -> Result<TokenStream, Error> { + Ok(match &ctx.ast.data { + Data::Struct(strct) => { + ImplBlockBuilder::new(ctx, strct, Trait::Immutable, FieldBounds::ALL_SELF).build() + } + Data::Enum(enm) => { + ImplBlockBuilder::new(ctx, enm, Trait::Immutable, FieldBounds::ALL_SELF).build() + } + Data::Union(unn) => { + ImplBlockBuilder::new(ctx, unn, Trait::Immutable, FieldBounds::ALL_SELF).build() + } + }) +} + +pub(crate) fn derive_hash(ctx: &Ctx, _top_level: Trait) -> Result<TokenStream, Error> { + // This doesn't delegate to `impl_block` because `impl_block` assumes it is + // deriving a `zerocopy`-defined trait, and these trait impls share a common + // shape that `Hash` does not. In particular, `zerocopy` traits contain a + // method that only `zerocopy_derive` macros are supposed to implement, and + // `impl_block` generating this trait method is incompatible with `Hash`. + let type_ident = &ctx.ast.ident; + let (impl_generics, ty_generics, where_clause) = ctx.ast.generics.split_for_impl(); + let where_predicates = where_clause.map(|clause| &clause.predicates); + let zerocopy_crate = &ctx.zerocopy_crate; + let core = ctx.core_path(); + Ok(quote! { + impl #impl_generics #core::hash::Hash for #type_ident #ty_generics + where + Self: #zerocopy_crate::IntoBytes + #zerocopy_crate::Immutable, + #where_predicates + { + fn hash<H: #core::hash::Hasher>(&self, state: &mut H) { + #core::hash::Hasher::write(state, #zerocopy_crate::IntoBytes::as_bytes(self)) + } + + fn hash_slice<H: #core::hash::Hasher>(data: &[Self], state: &mut H) { + #core::hash::Hasher::write(state, #zerocopy_crate::IntoBytes::as_bytes(data)) + } + } + }) +} + +pub(crate) fn derive_eq(ctx: &Ctx, _top_level: Trait) -> Result<TokenStream, Error> { + // This doesn't delegate to `impl_block` because `impl_block` assumes it is + // deriving a `zerocopy`-defined trait, and these trait impls share a common + // shape that `Eq` does not. In particular, `zerocopy` traits contain a + // method that only `zerocopy_derive` macros are supposed to implement, and + // `impl_block` generating this trait method is incompatible with `Eq`. + let type_ident = &ctx.ast.ident; + let (impl_generics, ty_generics, where_clause) = ctx.ast.generics.split_for_impl(); + let where_predicates = where_clause.map(|clause| &clause.predicates); + let zerocopy_crate = &ctx.zerocopy_crate; + let core = ctx.core_path(); + Ok(quote! { + impl #impl_generics #core::cmp::PartialEq for #type_ident #ty_generics + where + Self: #zerocopy_crate::IntoBytes + #zerocopy_crate::Immutable, + #where_predicates + { + fn eq(&self, other: &Self) -> bool { + #core::cmp::PartialEq::eq( + #zerocopy_crate::IntoBytes::as_bytes(self), + #zerocopy_crate::IntoBytes::as_bytes(other), + ) + } + } + + impl #impl_generics #core::cmp::Eq for #type_ident #ty_generics + where + Self: #zerocopy_crate::IntoBytes + #zerocopy_crate::Immutable, + #where_predicates + { + } + }) +} + +pub(crate) fn derive_split_at(ctx: &Ctx, _top_level: Trait) -> Result<TokenStream, Error> { + let repr = StructUnionRepr::from_attrs(&ctx.ast.attrs)?; + + match &ctx.ast.data { + Data::Struct(_) => {} + Data::Enum(_) | Data::Union(_) => { + return ctx + .error_or_skip(Error::new(Span::call_site(), "can only be applied to structs")); + } + }; + + if repr.get_packed().is_some() { + return ctx.error_or_skip(Error::new( + Span::call_site(), + "must not have #[repr(packed)] attribute", + )); + } + + if !(repr.is_c() || repr.is_transparent()) { + return ctx.error_or_skip(Error::new( + Span::call_site(), + "must have #[repr(C)] or #[repr(transparent)] in order to guarantee this type's layout is splitable", + )); + } + + let fields = ctx.ast.data.fields(); + let trailing_field = if let Some(((_, _, trailing_field), _)) = fields.split_last() { + trailing_field + } else { + return ctx.error_or_skip(Error::new(Span::call_site(), "must at least one field")); + }; + + let zerocopy_crate = &ctx.zerocopy_crate; + // SAFETY: `#ty`, per the above checks, is `repr(C)` or `repr(transparent)` + // and is not packed; its trailing field is guaranteed to be well-aligned + // for its type. By invariant on `FieldBounds::TRAILING_SELF`, the trailing + // slice of the trailing field is also well-aligned for its type. + Ok(ImplBlockBuilder::new(ctx, &ctx.ast.data, Trait::SplitAt, FieldBounds::TRAILING_SELF) + .inner_extras(quote! { + type Elem = <#trailing_field as #zerocopy_crate::SplitAt>::Elem; + }) + .build()) +} |
