compiler/rust: Move VecPair from NAK to shared compiler crate
Some checks are pending
macOS-CI / macOS-CI (dri) (push) Waiting to run
macOS-CI / macOS-CI (xlib) (push) Waiting to run

Move the VecPair<A, B> data structure from NAK's ir.rs to the shared
compiler Rust crate so it can be reused by other backends.

The fields are private, and NAK's ir.rs (now in a different crate)
needs to read and mutate the inner Vecs. Add a_as_slice(..),
a_as_mut_slice(..), b_as_slice(..) and b_as_mut_slice(..), and update
NAK's SrcsAsSlice and DstsAsSlice impls to call them. Returning slices
keeps callers from changing the length of one side without the other,
which is what VecPair is built to prevent.

Signed-off-by: Christian Gmeiner <cgmeiner@igalia.com>
Reviewed-by: Mel Henning <mhenning@darkrefraction.com>
Reviewed-by: Faith Ekstrand <faith.ekstrand@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/41435>
This commit is contained in:
Christian Gmeiner 2026-04-02 13:46:05 +02:00 committed by Marge Bot
parent a18c07dc36
commit e201d4fa77
4 changed files with 115 additions and 92 deletions

View file

@ -11,3 +11,4 @@ pub mod memstream;
pub mod nir;
pub mod nir_instr_printer;
pub mod smallvec;
pub mod vec_pair;

View file

@ -11,6 +11,7 @@ _compiler_rs_sources = [
'nir_instr_printer.rs',
'nir.rs',
'smallvec.rs',
'vec_pair.rs',
]
_compiler_binding_types = [

View file

@ -0,0 +1,104 @@
// Copyright © 2022 Collabora, Ltd.
// SPDX-License-Identifier: MIT
use std::iter::Zip;
use std::slice;
pub struct VecPair<A, B> {
a: Vec<A>,
b: Vec<B>,
}
impl<A, B> VecPair<A, B> {
pub fn a_as_slice(&self) -> &[A] {
&self.a
}
pub fn a_as_mut_slice(&mut self) -> &mut [A] {
&mut self.a
}
pub fn b_as_slice(&self) -> &[B] {
&self.b
}
pub fn b_as_mut_slice(&mut self) -> &mut [B] {
&mut self.b
}
pub fn append(&mut self, other: &mut VecPair<A, B>) {
self.a.append(&mut other.a);
self.b.append(&mut other.b);
}
pub fn is_empty(&self) -> bool {
debug_assert!(self.a.len() == self.b.len());
self.a.is_empty()
}
pub fn iter(&self) -> Zip<slice::Iter<'_, A>, slice::Iter<'_, B>> {
debug_assert!(self.a.len() == self.b.len());
self.a.iter().zip(self.b.iter())
}
pub fn iter_mut(
&mut self,
) -> Zip<slice::IterMut<'_, A>, slice::IterMut<'_, B>> {
debug_assert!(self.a.len() == self.b.len());
self.a.iter_mut().zip(self.b.iter_mut())
}
pub fn len(&self) -> usize {
debug_assert!(self.a.len() == self.b.len());
self.a.len()
}
pub fn new() -> Self {
Self {
a: Vec::new(),
b: Vec::new(),
}
}
pub fn push(&mut self, a: A, b: B) {
debug_assert!(self.a.len() == self.b.len());
self.a.push(a);
self.b.push(b);
}
}
impl<A: Clone, B: Clone> VecPair<A, B> {
pub fn retain(&mut self, mut f: impl FnMut(&A, &B) -> bool) {
debug_assert!(self.a.len() == self.b.len());
let len = self.a.len();
let mut i = 0_usize;
while i < len {
if !f(&self.a[i], &self.b[i]) {
break;
}
i += 1;
}
let mut new_len = i;
// Don't check this one twice.
i += 1;
while i < len {
// This could be more efficient but it's good enough for our
// purposes since everything we're storing is small and has a
// trivial Drop.
if f(&self.a[i], &self.b[i]) {
self.a[new_len] = self.a[i].clone();
self.b[new_len] = self.b[i].clone();
new_len += 1;
}
i += 1;
}
if new_len < len {
self.a.truncate(new_len);
self.b.truncate(new_len);
}
}
}

View file

@ -19,11 +19,11 @@ use compiler::as_slice::*;
use compiler::cfg::CFG;
use compiler::dataflow::ForwardDataflow;
use compiler::smallvec::SmallVec;
use compiler::vec_pair::VecPair;
use nak_ir_proc::*;
use std::cmp::{max, min};
use std::fmt;
use std::fmt::Write;
use std::iter::Zip;
use std::ops::{BitAnd, BitOr, Deref, DerefMut, Index, IndexMut, Not, Range};
use std::slice;
@ -7627,89 +7627,6 @@ impl DisplayOp for OpSrcBar {
}
impl_display_for_op!(OpSrcBar);
pub struct VecPair<A, B> {
a: Vec<A>,
b: Vec<B>,
}
impl<A, B> VecPair<A, B> {
pub fn append(&mut self, other: &mut VecPair<A, B>) {
self.a.append(&mut other.a);
self.b.append(&mut other.b);
}
pub fn is_empty(&self) -> bool {
debug_assert!(self.a.len() == self.b.len());
self.a.is_empty()
}
pub fn iter(&self) -> Zip<slice::Iter<'_, A>, slice::Iter<'_, B>> {
debug_assert!(self.a.len() == self.b.len());
self.a.iter().zip(self.b.iter())
}
pub fn iter_mut(
&mut self,
) -> Zip<slice::IterMut<'_, A>, slice::IterMut<'_, B>> {
debug_assert!(self.a.len() == self.b.len());
self.a.iter_mut().zip(self.b.iter_mut())
}
pub fn len(&self) -> usize {
debug_assert!(self.a.len() == self.b.len());
self.a.len()
}
pub fn new() -> Self {
Self {
a: Vec::new(),
b: Vec::new(),
}
}
pub fn push(&mut self, a: A, b: B) {
debug_assert!(self.a.len() == self.b.len());
self.a.push(a);
self.b.push(b);
}
}
impl<A: Clone, B: Clone> VecPair<A, B> {
pub fn retain(&mut self, mut f: impl FnMut(&A, &B) -> bool) {
debug_assert!(self.a.len() == self.b.len());
let len = self.a.len();
let mut i = 0_usize;
while i < len {
if !f(&self.a[i], &self.b[i]) {
break;
}
i += 1;
}
let mut new_len = i;
// Don't check this one twice.
i += 1;
while i < len {
// This could be more efficient but it's good enough for our
// purposes since everything we're storing is small and has a
// trivial Drop.
if f(&self.a[i], &self.b[i]) {
self.a[new_len] = self.a[i].clone();
self.b[new_len] = self.b[i].clone();
new_len += 1;
}
i += 1;
}
if new_len < len {
self.a.truncate(new_len);
self.b.truncate(new_len);
}
}
}
mod phi {
#[allow(unused_imports)]
use crate::ir::{OpPhiDsts, OpPhiSrcs};
@ -7804,11 +7721,11 @@ impl OpPhiSrcs {
impl SrcsAsSlice for OpPhiSrcs {
fn srcs_as_slice(&self) -> &[Src] {
&self.srcs.b
self.srcs.b_as_slice()
}
fn srcs_as_mut_slice(&mut self) -> &mut [Src] {
&mut self.srcs.b
self.srcs.b_as_mut_slice()
}
fn src_types(&self) -> SrcTypeList {
@ -7851,11 +7768,11 @@ impl OpPhiDsts {
impl DstsAsSlice for OpPhiDsts {
fn dsts_as_slice(&self) -> &[Dst] {
&self.dsts.b
self.dsts.b_as_slice()
}
fn dsts_as_mut_slice(&mut self) -> &mut [Dst] {
&mut self.dsts.b
self.dsts.b_as_mut_slice()
}
fn dst_types(&self) -> DstTypeList {
@ -7966,11 +7883,11 @@ impl OpParCopy {
impl SrcsAsSlice for OpParCopy {
fn srcs_as_slice(&self) -> &[Src] {
&self.dsts_srcs.b
self.dsts_srcs.b_as_slice()
}
fn srcs_as_mut_slice(&mut self) -> &mut [Src] {
&mut self.dsts_srcs.b
self.dsts_srcs.b_as_mut_slice()
}
fn src_types(&self) -> SrcTypeList {
@ -7980,11 +7897,11 @@ impl SrcsAsSlice for OpParCopy {
impl DstsAsSlice for OpParCopy {
fn dsts_as_slice(&self) -> &[Dst] {
&self.dsts_srcs.a
self.dsts_srcs.a_as_slice()
}
fn dsts_as_mut_slice(&mut self) -> &mut [Dst] {
&mut self.dsts_srcs.a
self.dsts_srcs.a_as_mut_slice()
}
fn dst_types(&self) -> DstTypeList {