mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-01-29 09:30:20 +01:00
This commit intorduces src/compiler/rust crate, which will have different modules that help to write a backend compiler in Rust. Signed-off-by: Christian Gmeiner <cgmeiner@igalia.com> Reviewed-by: Faith Ekstrand <faith.ekstrand@collabora.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/30443>
253 lines
5.8 KiB
Rust
253 lines
5.8 KiB
Rust
// Copyright © 2022 Collabora, Ltd.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
use std::ops::{
|
|
BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Not, Range,
|
|
};
|
|
|
|
#[derive(Clone)]
|
|
pub struct BitSet {
|
|
words: Vec<u32>,
|
|
}
|
|
|
|
impl BitSet {
|
|
pub fn new() -> BitSet {
|
|
BitSet { words: Vec::new() }
|
|
}
|
|
|
|
fn reserve_words(&mut self, words: usize) {
|
|
if self.words.len() < words {
|
|
self.words.resize(words, 0);
|
|
}
|
|
}
|
|
|
|
pub fn reserve(&mut self, bits: usize) {
|
|
self.reserve_words(bits.div_ceil(32));
|
|
}
|
|
|
|
pub fn clear(&mut self) {
|
|
for w in self.words.iter_mut() {
|
|
*w = 0;
|
|
}
|
|
}
|
|
|
|
pub fn get(&self, idx: usize) -> bool {
|
|
let w = idx / 32;
|
|
let b = idx % 32;
|
|
if w < self.words.len() {
|
|
self.words[w] & (1_u32 << b) != 0
|
|
} else {
|
|
false
|
|
}
|
|
}
|
|
|
|
pub fn is_empty(&self) -> bool {
|
|
for w in self.words.iter() {
|
|
if *w != 0 {
|
|
return false;
|
|
}
|
|
}
|
|
true
|
|
}
|
|
|
|
pub fn iter(&self) -> BitSetIter<'_> {
|
|
BitSetIter::new(self, 0)
|
|
}
|
|
|
|
pub fn get_word(&self, word: usize) -> u32 {
|
|
self.words.get(word).cloned().unwrap_or(0)
|
|
}
|
|
|
|
pub fn next_unset(&self, start: usize) -> usize {
|
|
if start >= self.words.len() * 32 {
|
|
return start;
|
|
}
|
|
|
|
let mut w = start / 32;
|
|
let mut mask = !(u32::MAX << (start % 32));
|
|
while w < self.words.len() {
|
|
let b = (self.words[w] | mask).trailing_ones();
|
|
if b < 32 {
|
|
return w * 32 + usize::try_from(b).unwrap();
|
|
}
|
|
mask = 0;
|
|
w += 1;
|
|
}
|
|
self.words.len() * 32
|
|
}
|
|
|
|
pub fn insert(&mut self, idx: usize) -> bool {
|
|
let w = idx / 32;
|
|
let b = idx % 32;
|
|
self.reserve_words(w + 1);
|
|
let exists = self.words[w] & (1_u32 << b) != 0;
|
|
self.words[w] |= 1_u32 << b;
|
|
!exists
|
|
}
|
|
|
|
pub fn remove(&mut self, idx: usize) -> bool {
|
|
let w = idx / 32;
|
|
let b = idx % 32;
|
|
self.reserve_words(w + 1);
|
|
let exists = self.words[w] & (1_u32 << b) != 0;
|
|
self.words[w] &= !(1_u32 << b);
|
|
exists
|
|
}
|
|
|
|
#[inline]
|
|
fn set_word(
|
|
&mut self,
|
|
w: usize,
|
|
mask: u32,
|
|
f: &mut impl FnMut(usize) -> u32,
|
|
) {
|
|
self.words[w] = (self.words[w] & !mask) | (f(w) & mask);
|
|
}
|
|
|
|
pub fn set_words(
|
|
&mut self,
|
|
bits: Range<usize>,
|
|
mut f: impl FnMut(usize) -> u32,
|
|
) {
|
|
if bits.is_empty() {
|
|
return;
|
|
}
|
|
|
|
let first_word = bits.start / 32;
|
|
let last_word = (bits.end - 1) / 32;
|
|
let start_mask = !0_u32 << (bits.start % 32);
|
|
let end_mask = !0_u32 >> (31 - ((bits.end - 1) % 32));
|
|
|
|
self.reserve(last_word + 1);
|
|
|
|
if first_word == last_word {
|
|
self.set_word(first_word, start_mask & end_mask, &mut f);
|
|
} else {
|
|
self.set_word(first_word, start_mask, &mut f);
|
|
for w in (first_word + 1)..last_word {
|
|
self.set_word(w, !0, &mut f);
|
|
}
|
|
self.set_word(last_word, end_mask, &mut f);
|
|
}
|
|
}
|
|
|
|
pub fn union_with(&mut self, other: &BitSet) -> bool {
|
|
let mut added_bits = false;
|
|
self.reserve_words(other.words.len());
|
|
for w in 0..other.words.len() {
|
|
let uw = self.words[w] | other.words[w];
|
|
if uw != self.words[w] {
|
|
added_bits = true;
|
|
self.words[w] = uw;
|
|
}
|
|
}
|
|
added_bits
|
|
}
|
|
}
|
|
|
|
impl Default for BitSet {
|
|
fn default() -> BitSet {
|
|
BitSet::new()
|
|
}
|
|
}
|
|
|
|
impl BitAndAssign for BitSet {
|
|
fn bitand_assign(&mut self, rhs: BitSet) {
|
|
self.reserve_words(rhs.words.len());
|
|
for w in 0..rhs.words.len() {
|
|
self.words[w] &= rhs.words[w];
|
|
}
|
|
}
|
|
}
|
|
|
|
impl BitAnd<BitSet> for BitSet {
|
|
type Output = BitSet;
|
|
|
|
fn bitand(self, rhs: BitSet) -> BitSet {
|
|
let mut res = self;
|
|
res.bitand_assign(rhs);
|
|
res
|
|
}
|
|
}
|
|
|
|
impl BitOrAssign for BitSet {
|
|
fn bitor_assign(&mut self, rhs: BitSet) {
|
|
self.reserve_words(rhs.words.len());
|
|
for w in 0..rhs.words.len() {
|
|
self.words[w] |= rhs.words[w];
|
|
}
|
|
}
|
|
}
|
|
|
|
impl BitOr<BitSet> for BitSet {
|
|
type Output = BitSet;
|
|
|
|
fn bitor(self, rhs: BitSet) -> BitSet {
|
|
let mut res = self;
|
|
res.bitor_assign(rhs);
|
|
res
|
|
}
|
|
}
|
|
|
|
impl BitXorAssign for BitSet {
|
|
fn bitxor_assign(&mut self, rhs: BitSet) {
|
|
self.reserve_words(rhs.words.len());
|
|
for w in 0..rhs.words.len() {
|
|
self.words[w] ^= rhs.words[w];
|
|
}
|
|
}
|
|
}
|
|
|
|
impl BitXor<BitSet> for BitSet {
|
|
type Output = BitSet;
|
|
|
|
fn bitxor(self, rhs: BitSet) -> BitSet {
|
|
let mut res = self;
|
|
res.bitxor_assign(rhs);
|
|
res
|
|
}
|
|
}
|
|
|
|
impl Not for BitSet {
|
|
type Output = BitSet;
|
|
|
|
fn not(self) -> BitSet {
|
|
let mut res = self;
|
|
for w in 0..res.words.len() {
|
|
res.words[w] = !res.words[w];
|
|
}
|
|
res
|
|
}
|
|
}
|
|
|
|
pub struct BitSetIter<'a> {
|
|
set: &'a BitSet,
|
|
w: usize,
|
|
mask: u32,
|
|
}
|
|
|
|
impl<'a> BitSetIter<'a> {
|
|
fn new(set: &'a BitSet, start: usize) -> Self {
|
|
Self {
|
|
set,
|
|
w: start / 32,
|
|
mask: u32::MAX << (start % 32),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<'a> Iterator for BitSetIter<'a> {
|
|
type Item = usize;
|
|
|
|
fn next(&mut self) -> Option<usize> {
|
|
while self.w < self.set.words.len() {
|
|
let b = (self.set.words[self.w] & self.mask).trailing_zeros();
|
|
if b < 32 {
|
|
return Some(self.w * 32 + usize::try_from(b).unwrap());
|
|
}
|
|
self.mask = u32::MAX;
|
|
self.w += 1;
|
|
}
|
|
None
|
|
}
|
|
}
|