Skip to main content

lamina_platform/
vector.rs

1//! Machine vector register widths, as a property of the target rather than a constant.
2
3use crate::arch_table::TargetArchitecture;
4
5impl TargetArchitecture {
6    /// Bit widths a vector register of this architecture comes in, ascending.
7    ///
8    /// Empty for an architecture whose backend emits no vector registers, and for a
9    /// scalable vector machine whose width is not a compile-time constant. A `<N x T>`
10    /// whose lanes do not add up to one of these has no register to live in.
11    pub fn vector_register_bits(self) -> &'static [u32] {
12        match self {
13            TargetArchitecture::X86_64 => &[128, 256],
14            TargetArchitecture::Aarch64
15            | TargetArchitecture::Armv7
16            | TargetArchitecture::Wasm32
17            | TargetArchitecture::Wasm64 => &[128],
18            TargetArchitecture::I686
19            | TargetArchitecture::Arm32
20            | TargetArchitecture::Thumbv6m
21            | TargetArchitecture::Thumbv7m
22            | TargetArchitecture::Riscv32
23            | TargetArchitecture::Riscv64
24            | TargetArchitecture::PowerPC64
25            | TargetArchitecture::PowerPC64Be
26            | TargetArchitecture::Mips64
27            | TargetArchitecture::Mips64El
28            | TargetArchitecture::LoongArch64
29            | TargetArchitecture::S390x
30            | TargetArchitecture::Nvptx64
31            | TargetArchitecture::Amdgcn => &[],
32            #[cfg(feature = "nightly")]
33            TargetArchitecture::Arx64 | TargetArchitecture::Riscv128 | TargetArchitecture::Lisa => {
34                &[]
35            }
36        }
37    }
38}
39
40/// Every vector register width some target has.
41///
42/// What a check with no target in hand can say: a width absent here fits no machine at
43/// all, while a width present here still has to be one the chosen target offers, which
44/// [`TargetArchitecture::vector_register_bits`] answers.
45pub fn any_vector_register_bits() -> &'static [u32] {
46    &[128, 256]
47}
48
49#[cfg(test)]
50mod tests {
51    use super::*;
52
53    #[test]
54    fn every_architecture_width_is_one_a_target_independent_check_allows() {
55        for architecture in TargetArchitecture::all() {
56            for bits in architecture.vector_register_bits() {
57                assert!(
58                    any_vector_register_bits().contains(bits),
59                    "{architecture:?} has {bits}-bit vectors that no target-independent check allows"
60                );
61            }
62        }
63    }
64
65    #[test]
66    fn widths_are_ascending_and_powers_of_two() {
67        for architecture in TargetArchitecture::all() {
68            let bits = architecture.vector_register_bits();
69            assert!(bits.windows(2).all(|w| w[0] < w[1]), "{architecture:?}");
70            assert!(bits.iter().all(|b| b.is_power_of_two()), "{architecture:?}");
71        }
72    }
73}