On Wed, May 21, 2025 at 12:23:02PM +0300, Manos Pitsidianakis wrote: > On Wed, May 21, 2025 at 11:29 AM Daniel P. Berrangé <berra...@redhat.com> > wrote: > > > > On Wed, May 21, 2025 at 10:18:40AM +0200, Paolo Bonzini wrote: > > > One common thing that device emulation does is manipulate bitmasks, for > > > example > > > to check whether two bitmaps have common bits. One example in the pl011 > > > crate > > > is the checks for pending interrupts, where an interrupt cause > > > corresponds to > > > at least one interrupt source from a fixed set. > > > > > > Unfortunately, this is one case where Rust *can* provide some kind of > > > abstraction but it does so with a rather Perl-ish There Is More Way To > > > Do It. It is not something where a crate like "bilge" helps, because > > > it only covers the packing of bits in a structure; operations like "are > > > all bits of Y set in X" almost never make sense for bit-packed structs; > > > you need something else, there are several crates that do it and of course > > > we're going to roll our own. > > > > > > In particular I examined three: > > > > > > - bitmask (https://docs.rs/bitmask/0.5.0/bitmask/) does not support const > > > at all. This is a showstopper because one of the ugly things in the > > > current pl011 code is the ugliness of code that defines interrupt masks > > > at compile time: > > > > > > pub const E: Self = Self(Self::OE.0 | Self::BE.0 | Self::PE.0 | > > > Self::FE.0); > > > > > > or even worse: > > > > > > const IRQMASK: [u32; 6] = [ > > > Interrupt::E.0 | Interrupt::MS.0 | Interrupt::RT.0 | > > > Interrupt::TX.0 | Interrupt::RX.0, > > > ... > > > } > > > > > > You would have to use roughly the same code---"bitmask" only helps with > > > defining the struct. > > > > > > - bitmask_enum (https://docs.rs/bitmask-enum/2.2.5/bitmask_enum/) does not > > > have a good separation of "valid" and "invalid" bits, so for example > > > "!x" > > > will invert all 16 bits if you choose u16 as the representation -- even > > > if > > > you only defined 10 bits. This makes it easier to introduce subtle bugs > > > in comparisons. > > > > > > - bitflags (https://docs.rs/bitflags/2.6.0/bitflags/) is generally the > > > most > > > used such crate and is the one that I took most inspiration from with > > > respect to the syntax. It's a pretty sophisticated implementation, > > > with a lot of bells and whistles such as an implementation of "Iter" > > > that returns the bits one at a time. > > > > > > The main thing that all of them lack, however, is a way to simplify the > > > ugly definitions like the above. "bitflags" includes const methods that > > > perform AND/OR/XOR of masks (these are necessary because Rust operator > > > overloading does not support const yet, and therefore overloaded operators > > > cannot be used in the definition of a "static" variable), but they become > > > even more verbose and unmanageable, like > > > > > > > > > Interrupt::E.union(Interrupt::MS).union(Interrupt::RT).union(Interrupt::TX).union(Interrupt::RX) > > > > > > This was the main reason to create "bits", which allows something like > > > > > > bits!(Interrupt: E | MS | RT | TX | RX) > > > > > > and expands it 1) add "Interrupt::" in front of all identifiers 2) convert > > > operators to the wordy const functions like "union". It supports boolean > > > operators "&", "|", "^", "!" and parentheses, with a relatively simple > > > recursive descent parser that's implemented in qemu_api_macros. > > > > > > Signed-off-by: Paolo Bonzini <pbonz...@redhat.com> > > > --- > > > rust/Cargo.lock | 7 + > > > rust/Cargo.toml | 1 + > > > rust/bits/Cargo.toml | 19 ++ > > > rust/bits/meson.build | 12 + > > > rust/bits/src/lib.rs | 441 +++++++++++++++++++++++++++++++ > > > rust/meson.build | 1 + > > > rust/qemu-api-macros/src/bits.rs | 227 ++++++++++++++++ > > > rust/qemu-api-macros/src/lib.rs | 12 + > > > 8 files changed, 720 insertions(+) > > > create mode 100644 rust/bits/Cargo.toml > > > create mode 100644 rust/bits/meson.build > > > create mode 100644 rust/bits/src/lib.rs > > > create mode 100644 rust/qemu-api-macros/src/bits.rs > > > > > diff --git a/rust/bits/src/lib.rs b/rust/bits/src/lib.rs > > > new file mode 100644 > > > index 00000000000..d80a6263f1e > > > --- /dev/null > > > +++ b/rust/bits/src/lib.rs > > > @@ -0,0 +1,441 @@ > > > > This (and other new .rs files) needs SPDX-License-Identifier > > We should probably lint for this in .rs files.
Strengthened from a recommendation to a mandate in: https://lists.nongnu.org/archive/html/qemu-devel/2025-05/msg04968.html With regards, Daniel -- |: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|