naga/proc/overloads/
scalar_set.rs1use crate::ir::Scalar;
4use crate::proc::overloads::one_bits_iter::OneBitsIter;
5
6macro_rules! define_scalar_set {
7    { $( $scalar:ident, )* } => {
8        #[expect(non_camel_case_types, clippy::upper_case_acronyms)]
10        #[repr(u32)]
11        enum ScalarSetBits {
12            $( $scalar, )*
13            Count,
14        }
15
16        static SCALARS_FOR_BITS: [Scalar; ScalarSetBits::Count as usize] = [
18            $(
19                Scalar::$scalar,
20            )*
21        ];
22
23        bitflags::bitflags! {
24            #[derive(Copy, Clone, Debug)]
32            pub(crate) struct ScalarSet: u16 {
33                $(
34                    const $scalar = 1 << (ScalarSetBits::$scalar as u32);
35                )*
36            }
37        }
38
39        impl ScalarSet {
40            #[expect(dead_code)]
42            pub const fn singleton(scalar: Scalar) -> Self {
43                match scalar {
44                    $(
45                        Scalar::$scalar => Self::$scalar,
46                    )*
47                    _ => Self::empty(),
48                }
49            }
50        }
51    }
52}
53
54define_scalar_set! {
55    ABSTRACT_INT, ABSTRACT_FLOAT,
61    I32, I64,
62    U32, U64,
63    F32, F16, F64,
64    BOOL,
65}
66
67impl ScalarSet {
68    pub fn convertible_from(scalar: Scalar) -> Self {
71        use Scalar as Sc;
72        match scalar {
73            Sc::I32 => Self::I32,
74            Sc::I64 => Self::I64,
75            Sc::U32 => Self::U32,
76            Sc::U64 => Self::U64,
77            Sc::F16 => Self::F16,
78            Sc::F32 => Self::F32,
79            Sc::F64 => Self::F64,
80            Sc::BOOL => Self::BOOL,
81            Sc::ABSTRACT_INT => Self::INTEGER | Self::FLOAT,
82            Sc::ABSTRACT_FLOAT => Self::FLOAT,
83            _ => Self::empty(),
84        }
85    }
86
87    pub fn most_general_scalar(self) -> Scalar {
93        let lowest = self.bits().trailing_zeros();
97        *SCALARS_FOR_BITS.get(lowest as usize).unwrap()
98    }
99
100    pub fn members(self) -> impl Iterator<Item = ScalarSet> {
104        OneBitsIter::new(self.bits() as u64).map(|bit| Self::from_bits(bit as u16).unwrap())
105    }
106
107    pub const FLOAT: Self = Self::ABSTRACT_FLOAT
108        .union(Self::F16)
109        .union(Self::F32)
110        .union(Self::F64);
111
112    pub const INTEGER: Self = Self::ABSTRACT_INT
113        .union(Self::I32)
114        .union(Self::I64)
115        .union(Self::U32)
116        .union(Self::U64);
117
118    pub const NUMERIC: Self = Self::FLOAT.union(Self::INTEGER);
119    pub const ABSTRACT: Self = Self::ABSTRACT_INT.union(Self::ABSTRACT_FLOAT);
120    pub const CONCRETE: Self = Self::all().difference(Self::ABSTRACT);
121    pub const CONCRETE_INTEGER: Self = Self::INTEGER.intersection(Self::CONCRETE);
122    pub const CONCRETE_FLOAT: Self = Self::FLOAT.intersection(Self::CONCRETE);
123
124    pub const FLOAT_ABSTRACT_UNIMPLEMENTED: Self = Self::CONCRETE_FLOAT;
127}
128
129macro_rules! scalar_set {
130    ( $( $scalar:ident )|* ) => {
131        {
132            use $crate::proc::overloads::scalar_set::ScalarSet;
133            ScalarSet::empty()
134                $(
135                    .union(ScalarSet::$scalar)
136                )*
137        }
138    }
139}
140
141pub(in crate::proc::overloads) use scalar_set;